1/* $NetBSD: zone.c,v 1.5 2019/04/28 00:01:14 christos Exp $ */
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14/*! \file */
15
16#include <config.h>
17
18#include <errno.h>
19#include <inttypes.h>
20#include <stdbool.h>
21
22#include <isc/file.h>
23#include <isc/hex.h>
24#include <isc/mutex.h>
25#include <isc/pool.h>
26#include <isc/print.h>
27#include <isc/random.h>
28#include <isc/ratelimiter.h>
29#include <isc/refcount.h>
30#include <isc/rwlock.h>
31#include <isc/serial.h>
32#include <isc/stats.h>
33#include <isc/stdtime.h>
34#include <isc/strerr.h>
35#include <isc/string.h>
36#include <isc/taskpool.h>
37#include <isc/thread.h>
38#include <isc/timer.h>
39#include <isc/util.h>
40
41#include <dns/acl.h>
42#include <dns/adb.h>
43#include <dns/callbacks.h>
44#include <dns/catz.h>
45#include <dns/db.h>
46#include <dns/dbiterator.h>
47#include <dns/dlz.h>
48#include <dns/dnssec.h>
49#include <dns/events.h>
50#include <dns/journal.h>
51#include <dns/keydata.h>
52#include <dns/keytable.h>
53#include <dns/keyvalues.h>
54#include <dns/log.h>
55#include <dns/master.h>
56#include <dns/masterdump.h>
57#include <dns/message.h>
58#include <dns/name.h>
59#include <dns/nsec.h>
60#include <dns/nsec3.h>
61#include <dns/peer.h>
62#include <dns/private.h>
63#include <dns/rcode.h>
64#include <dns/rdata.h>
65#include <dns/rdataclass.h>
66#include <dns/rdatalist.h>
67#include <dns/rdataset.h>
68#include <dns/rdatasetiter.h>
69#include <dns/rdatastruct.h>
70#include <dns/rdatatype.h>
71#include <dns/request.h>
72#include <dns/resolver.h>
73#include <dns/result.h>
74#include <dns/rriterator.h>
75#include <dns/soa.h>
76#include <dns/ssu.h>
77#include <dns/stats.h>
78#include <dns/time.h>
79#include <dns/tsig.h>
80#include <dns/update.h>
81#include <dns/xfrin.h>
82#include <dns/zone.h>
83#include <dns/zoneverify.h>
84#include <dns/zt.h>
85
86#include <dst/dst.h>
87
88#include "zone_p.h"
89
90#define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
91#define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
92
93#define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
94#define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
95
96#define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
97#define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
98
99#define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
100#define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
101
102#define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
103#define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
104
105#define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
106#define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
107
108#define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
109#define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
110
111/*%
112 * Ensure 'a' is at least 'min' but not more than 'max'.
113 */
114#define RANGE(a, min, max) \
115 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
116
117#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
118
119/*%
120 * Key flags
121 */
122#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
123#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
124#define ALG(x) dst_key_alg(x)
125
126/*
127 * Default values.
128 */
129#define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
130#define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
131#define MAX_XFER_TIME (2*3600) /*%< Documented default is 2 hours */
132#define RESIGN_DELAY 3600 /*%< 1 hour */
133
134#ifndef DNS_MAX_EXPIRE
135#define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
136#endif
137
138#ifndef DNS_DUMP_DELAY
139#define DNS_DUMP_DELAY 900 /*%< 15 minutes */
140#endif
141
142typedef struct dns_notify dns_notify_t;
143typedef struct dns_stub dns_stub_t;
144typedef struct dns_load dns_load_t;
145typedef struct dns_forward dns_forward_t;
146typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
147typedef struct dns_io dns_io_t;
148typedef ISC_LIST(dns_io_t) dns_iolist_t;
149typedef struct dns_signing dns_signing_t;
150typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
151typedef struct dns_nsec3chain dns_nsec3chain_t;
152typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
153typedef struct dns_keyfetch dns_keyfetch_t;
154typedef struct dns_asyncload dns_asyncload_t;
155typedef struct dns_include dns_include_t;
156
157#define DNS_ZONE_CHECKLOCK
158#ifdef DNS_ZONE_CHECKLOCK
159#define LOCK_ZONE(z) \
160 do { LOCK(&(z)->lock); \
161 INSIST((z)->locked == false); \
162 (z)->locked = true; \
163 } while (/*CONSTCOND*/0)
164#define UNLOCK_ZONE(z) \
165 do { (z)->locked = false; UNLOCK(&(z)->lock); } while (/*CONSTCON*/0)
166#define LOCKED_ZONE(z) ((z)->locked)
167#define TRYLOCK_ZONE(result, z) \
168 do { \
169 result = isc_mutex_trylock(&(z)->lock); \
170 if (result == ISC_R_SUCCESS) { \
171 INSIST((z)->locked == false); \
172 (z)->locked = true; \
173 } \
174 } while (/*CONSTCOND*/0)
175#else
176#define LOCK_ZONE(z) LOCK(&(z)->lock)
177#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
178#define LOCKED_ZONE(z) true
179#define TRYLOCK_ZONE(result, z) \
180 do { result = isc_mutex_trylock(&(z)->lock); } while (/*CONSTCOND*/0)
181#endif
182
183#define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
184#define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
185#define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
186#define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
187
188#ifdef ENABLE_AFL
189extern bool dns_fuzzing_resolver;
190#endif
191
192struct dns_zone {
193 /* Unlocked */
194 unsigned int magic;
195 isc_mutex_t lock;
196#ifdef DNS_ZONE_CHECKLOCK
197 bool locked;
198#endif
199 isc_mem_t *mctx;
200 isc_refcount_t erefs;
201
202 isc_rwlock_t dblock;
203 dns_db_t *db; /* Locked by dblock */
204
205 /* Locked */
206 dns_zonemgr_t *zmgr;
207 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
208 isc_timer_t *timer;
209 unsigned int irefs;
210 dns_name_t origin;
211 char *masterfile;
212 ISC_LIST(dns_include_t) includes; /* Include files */
213 ISC_LIST(dns_include_t) newincludes; /* Loading */
214 unsigned int nincludes;
215 dns_masterformat_t masterformat;
216 const dns_master_style_t *masterstyle;
217 char *journal;
218 int32_t journalsize;
219 dns_rdataclass_t rdclass;
220 dns_zonetype_t type;
221 unsigned int flags;
222 dns_zoneopt_t options;
223 unsigned int db_argc;
224 char **db_argv;
225 isc_time_t expiretime;
226 isc_time_t refreshtime;
227 isc_time_t dumptime;
228 isc_time_t loadtime;
229 isc_time_t notifytime;
230 isc_time_t resigntime;
231 isc_time_t keywarntime;
232 isc_time_t signingtime;
233 isc_time_t nsec3chaintime;
234 isc_time_t refreshkeytime;
235 uint32_t refreshkeyinterval;
236 uint32_t refreshkeycount;
237 uint32_t refresh;
238 uint32_t retry;
239 uint32_t expire;
240 uint32_t minimum;
241 isc_stdtime_t key_expiry;
242 isc_stdtime_t log_key_expired_timer;
243 char *keydirectory;
244
245 uint32_t maxrefresh;
246 uint32_t minrefresh;
247 uint32_t maxretry;
248 uint32_t minretry;
249
250 uint32_t maxrecords;
251
252 isc_sockaddr_t *masters;
253 isc_dscp_t *masterdscps;
254 dns_name_t **masterkeynames;
255 bool *mastersok;
256 unsigned int masterscnt;
257 unsigned int curmaster;
258 isc_sockaddr_t masteraddr;
259 dns_notifytype_t notifytype;
260 isc_sockaddr_t *notify;
261 dns_name_t **notifykeynames;
262 isc_dscp_t *notifydscp;
263 unsigned int notifycnt;
264 isc_sockaddr_t notifyfrom;
265 isc_task_t *task;
266 isc_task_t *loadtask;
267 isc_sockaddr_t notifysrc4;
268 isc_sockaddr_t notifysrc6;
269 isc_sockaddr_t xfrsource4;
270 isc_sockaddr_t xfrsource6;
271 isc_sockaddr_t altxfrsource4;
272 isc_sockaddr_t altxfrsource6;
273 isc_sockaddr_t sourceaddr;
274 isc_dscp_t notifysrc4dscp;
275 isc_dscp_t notifysrc6dscp;
276 isc_dscp_t xfrsource4dscp;
277 isc_dscp_t xfrsource6dscp;
278 isc_dscp_t altxfrsource4dscp;
279 isc_dscp_t altxfrsource6dscp;
280 dns_xfrin_ctx_t *xfr; /* task locked */
281 dns_tsigkey_t *tsigkey; /* key used for xfr */
282 /* Access Control Lists */
283 dns_acl_t *update_acl;
284 dns_acl_t *forward_acl;
285 dns_acl_t *notify_acl;
286 dns_acl_t *query_acl;
287 dns_acl_t *queryon_acl;
288 dns_acl_t *xfr_acl;
289 bool update_disabled;
290 bool zero_no_soa_ttl;
291 dns_severity_t check_names;
292 ISC_LIST(dns_notify_t) notifies;
293 dns_request_t *request;
294 dns_loadctx_t *lctx;
295 dns_io_t *readio;
296 dns_dumpctx_t *dctx;
297 dns_io_t *writeio;
298 uint32_t maxxfrin;
299 uint32_t maxxfrout;
300 uint32_t idlein;
301 uint32_t idleout;
302 isc_event_t ctlevent;
303 dns_ssutable_t *ssutable;
304 uint32_t sigvalidityinterval;
305 uint32_t keyvalidityinterval;
306 uint32_t sigresigninginterval;
307 dns_view_t *view;
308 dns_view_t *prev_view;
309 dns_checkmxfunc_t checkmx;
310 dns_checksrvfunc_t checksrv;
311 dns_checknsfunc_t checkns;
312 /*%
313 * Zones in certain states such as "waiting for zone transfer"
314 * or "zone transfer in progress" are kept on per-state linked lists
315 * in the zone manager using the 'statelink' field. The 'statelist'
316 * field points at the list the zone is currently on. It the zone
317 * is not on any such list, statelist is NULL.
318 */
319 ISC_LINK(dns_zone_t) statelink;
320 dns_zonelist_t *statelist;
321 /*%
322 * Statistics counters about zone management.
323 */
324 isc_stats_t *stats;
325 /*%
326 * Optional per-zone statistics counters. Counted outside of this
327 * module.
328 */
329 dns_zonestat_level_t statlevel;
330 bool requeststats_on;
331 isc_stats_t *requeststats;
332 dns_stats_t *rcvquerystats;
333 uint32_t notifydelay;
334 dns_isselffunc_t isself;
335 void *isselfarg;
336
337 char * strnamerd;
338 char * strname;
339 char * strrdclass;
340 char * strviewname;
341
342 /*%
343 * Serial number for deferred journal compaction.
344 */
345 uint32_t compact_serial;
346 /*%
347 * Keys that are signing the zone for the first time.
348 */
349 dns_signinglist_t signing;
350 dns_nsec3chainlist_t nsec3chain;
351 /*%
352 * List of outstanding NSEC3PARAM change requests.
353 */
354 isc_eventlist_t setnsec3param_queue;
355 /*%
356 * Signing / re-signing quantum stopping parameters.
357 */
358 uint32_t signatures;
359 uint32_t nodes;
360 dns_rdatatype_t privatetype;
361
362 /*%
363 * Autosigning/key-maintenance options
364 */
365 uint32_t keyopts;
366
367 /*%
368 * True if added by "rndc addzone"
369 */
370 bool added;
371
372 /*%
373 * True if added by automatically by named.
374 */
375 bool automatic;
376
377 /*%
378 * response policy data to be relayed to the database
379 */
380 dns_rpz_zones_t *rpzs;
381 dns_rpz_num_t rpz_num;
382
383 /*%
384 * catalog zone data
385 */
386 dns_catz_zones_t *catzs;
387
388 /*%
389 * parent catalog zone
390 */
391 dns_catz_zone_t *parentcatz;
392
393 /*%
394 * Serial number update method.
395 */
396 dns_updatemethod_t updatemethod;
397
398 /*%
399 * whether ixfr is requested
400 */
401 bool requestixfr;
402
403 /*%
404 * whether EDNS EXPIRE is requested
405 */
406 bool requestexpire;
407
408 /*%
409 * Outstanding forwarded UPDATE requests.
410 */
411 dns_forwardlist_t forwards;
412
413 dns_zone_t *raw;
414 dns_zone_t *secure;
415
416 bool sourceserialset;
417 uint32_t sourceserial;
418
419 /*%
420 * maximum zone ttl
421 */
422 dns_ttl_t maxttl;
423
424 /*
425 * Inline zone signing state.
426 */
427 dns_diff_t rss_diff;
428 isc_eventlist_t rss_events;
429 dns_dbversion_t *rss_newver;
430 dns_dbversion_t *rss_oldver;
431 dns_db_t *rss_db;
432 dns_zone_t *rss_raw;
433 isc_event_t *rss_event;
434 dns_update_state_t *rss_state;
435
436 isc_stats_t *gluecachestats;
437};
438
439#define zonediff_init(z, d) \
440 do { \
441 dns__zonediff_t *_z = (z); \
442 (_z)->diff = (d); \
443 (_z)->offline = false; \
444 } while (/*CONSTCOND*/0)
445
446#define DNS_ZONE_FLAG(z,f) ((z)->flags & (f))
447#define DNS_ZONE_SETFLAG(z,f) do { \
448 INSIST(LOCKED_ZONE(z)); \
449 (z)->flags |= (f); \
450 } while (/*CONSTCOND*/0)
451#define DNS_ZONE_CLRFLAG(z,f) do { \
452 INSIST(LOCKED_ZONE(z)); \
453 (z)->flags &= ~(f); \
454 } while (/*CONSTCOND*/0)
455 /* XXX MPA these may need to go back into zone.h */
456#define DNS_ZONEFLG_REFRESH 0x00000001U /*%< refresh check in progress */
457#define DNS_ZONEFLG_NEEDDUMP 0x00000002U /*%< zone need consolidation */
458#define DNS_ZONEFLG_USEVC 0x00000004U /*%< use tcp for refresh query */
459#define DNS_ZONEFLG_DUMPING 0x00000008U /*%< a dump is in progress */
460#define DNS_ZONEFLG_HASINCLUDE 0x00000010U /*%< $INCLUDE in zone file */
461#define DNS_ZONEFLG_LOADED 0x00000020U /*%< database has loaded */
462#define DNS_ZONEFLG_EXITING 0x00000040U /*%< zone is being destroyed */
463#define DNS_ZONEFLG_EXPIRED 0x00000080U /*%< zone has expired */
464#define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /*%< refresh check needed */
465#define DNS_ZONEFLG_UPTODATE 0x00000200U /*%< zone contents are
466 * uptodate */
467#define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /*%< need to send out notify
468 * messages */
469#define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /*%< generate a journal diff on
470 * reload */
471#define DNS_ZONEFLG_NOMASTERS 0x00001000U /*%< an attempt to refresh a
472 * zone with no masters
473 * occurred */
474#define DNS_ZONEFLG_LOADING 0x00002000U /*%< load from disk in progress*/
475#define DNS_ZONEFLG_HAVETIMERS 0x00004000U /*%< timer values have been set
476 * from SOA (if not set, we
477 * are still using
478 * default timer values) */
479#define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */
480#define DNS_ZONEFLG_NOREFRESH 0x00010000U
481#define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
482#define DNS_ZONEFLG_DIALREFRESH 0x00040000U
483#define DNS_ZONEFLG_SHUTDOWN 0x00080000U
484#define DNS_ZONEFLAG_NOIXFR 0x00100000U /*%< IXFR failed, force AXFR */
485#define DNS_ZONEFLG_FLUSH 0x00200000U
486#define DNS_ZONEFLG_NOEDNS 0x00400000U
487#define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
488#define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
489#define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
490#define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */
491#define DNS_ZONEFLG_THAW 0x08000000U
492#define DNS_ZONEFLG_LOADPENDING 0x10000000U /*%< Loading scheduled */
493#define DNS_ZONEFLG_NODELAY 0x20000000U
494#define DNS_ZONEFLG_SENDSECURE 0x40000000U
495#define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify
496 * due to the zone just
497 * being loaded for the
498 * first time. */
499
500#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
501#define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
502
503/* Flags for zone_load() */
504#define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
505#define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful
506 load. */
507
508#define UNREACH_CHACHE_SIZE 10U
509#define UNREACH_HOLD_TIME 600 /* 10 minutes */
510
511#define CHECK(op) \
512 do { result = (op); \
513 if (result != ISC_R_SUCCESS) goto failure; \
514 } while (/*CONSTCOND*/0)
515
516struct dns_unreachable {
517 isc_sockaddr_t remote;
518 isc_sockaddr_t local;
519 uint32_t expire;
520 uint32_t last;
521 uint32_t count;
522};
523
524struct dns_zonemgr {
525 unsigned int magic;
526 isc_mem_t * mctx;
527 int refs; /* Locked by rwlock */
528 isc_taskmgr_t * taskmgr;
529 isc_timermgr_t * timermgr;
530 isc_socketmgr_t * socketmgr;
531 isc_taskpool_t * zonetasks;
532 isc_taskpool_t * loadtasks;
533 isc_task_t * task;
534 isc_pool_t * mctxpool;
535 isc_ratelimiter_t * notifyrl;
536 isc_ratelimiter_t * refreshrl;
537 isc_ratelimiter_t * startupnotifyrl;
538 isc_ratelimiter_t * startuprefreshrl;
539 isc_rwlock_t rwlock;
540 isc_mutex_t iolock;
541 isc_rwlock_t urlock;
542
543 /* Locked by rwlock. */
544 dns_zonelist_t zones;
545 dns_zonelist_t waiting_for_xfrin;
546 dns_zonelist_t xfrin_in_progress;
547
548 /* Configuration data. */
549 uint32_t transfersin;
550 uint32_t transfersperns;
551 unsigned int notifyrate;
552 unsigned int startupnotifyrate;
553 unsigned int serialqueryrate;
554 unsigned int startupserialqueryrate;
555
556 /* Locked by iolock */
557 uint32_t iolimit;
558 uint32_t ioactive;
559 dns_iolist_t high;
560 dns_iolist_t low;
561
562 /* Locked by urlock. */
563 /* LRU cache */
564 struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
565};
566
567/*%
568 * Hold notify state.
569 */
570struct dns_notify {
571 unsigned int magic;
572 unsigned int flags;
573 isc_mem_t *mctx;
574 dns_zone_t *zone;
575 dns_adbfind_t *find;
576 dns_request_t *request;
577 dns_name_t ns;
578 isc_sockaddr_t dst;
579 dns_tsigkey_t *key;
580 isc_dscp_t dscp;
581 ISC_LINK(dns_notify_t) link;
582 isc_event_t *event;
583};
584
585#define DNS_NOTIFY_NOSOA 0x0001U
586#define DNS_NOTIFY_STARTUP 0x0002U
587
588/*%
589 * dns_stub holds state while performing a 'stub' transfer.
590 * 'db' is the zone's 'db' or a new one if this is the initial
591 * transfer.
592 */
593
594struct dns_stub {
595 unsigned int magic;
596 isc_mem_t *mctx;
597 dns_zone_t *zone;
598 dns_db_t *db;
599 dns_dbversion_t *version;
600};
601
602/*%
603 * Hold load state.
604 */
605struct dns_load {
606 unsigned int magic;
607 isc_mem_t *mctx;
608 dns_zone_t *zone;
609 dns_db_t *db;
610 isc_time_t loadtime;
611 dns_rdatacallbacks_t callbacks;
612};
613
614/*%
615 * Hold forward state.
616 */
617struct dns_forward {
618 unsigned int magic;
619 isc_mem_t *mctx;
620 dns_zone_t *zone;
621 isc_buffer_t *msgbuf;
622 dns_request_t *request;
623 uint32_t which;
624 isc_sockaddr_t addr;
625 dns_updatecallback_t callback;
626 void *callback_arg;
627 unsigned int options;
628 ISC_LINK(dns_forward_t) link;
629};
630
631/*%
632 * Hold IO request state.
633 */
634struct dns_io {
635 unsigned int magic;
636 dns_zonemgr_t *zmgr;
637 bool high;
638 isc_task_t *task;
639 ISC_LINK(dns_io_t) link;
640 isc_event_t *event;
641};
642
643/*%
644 * Hold state for when we are signing a zone with a new
645 * DNSKEY as result of an update.
646 */
647struct dns_signing {
648 unsigned int magic;
649 dns_db_t *db;
650 dns_dbiterator_t *dbiterator;
651 dns_secalg_t algorithm;
652 uint16_t keyid;
653 bool deleteit;
654 bool done;
655 ISC_LINK(dns_signing_t) link;
656};
657
658struct dns_nsec3chain {
659 unsigned int magic;
660 dns_db_t *db;
661 dns_dbiterator_t *dbiterator;
662 dns_rdata_nsec3param_t nsec3param;
663 unsigned char salt[255];
664 bool done;
665 bool seen_nsec;
666 bool delete_nsec;
667 bool save_delete_nsec;
668 ISC_LINK(dns_nsec3chain_t) link;
669};
670/*%<
671 * 'dbiterator' contains a iterator for the database. If we are creating
672 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
673 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
674 * iterated.
675 *
676 * 'nsec3param' contains the parameters of the NSEC3 chain being created
677 * or removed.
678 *
679 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
680 *
681 * 'seen_nsec' will be set to true if, while iterating the zone to create a
682 * NSEC3 chain, a NSEC record is seen.
683 *
684 * 'delete_nsec' will be set to true if, at the completion of the creation
685 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
686 * are in the process of deleting the NSEC chain.
687 *
688 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
689 * so it can be recovered in the event of a error.
690 */
691
692struct dns_keyfetch {
693 dns_fixedname_t name;
694 dns_rdataset_t keydataset;
695 dns_rdataset_t dnskeyset;
696 dns_rdataset_t dnskeysigset;
697 dns_zone_t *zone;
698 dns_db_t *db;
699 dns_fetch_t *fetch;
700};
701
702/*%
703 * Hold state for an asynchronous load
704 */
705struct dns_asyncload {
706 dns_zone_t *zone;
707 unsigned int flags;
708 dns_zt_zoneloaded_t loaded;
709 void *loaded_arg;
710};
711
712/*%
713 * Reference to an include file encountered during loading
714 */
715struct dns_include {
716 char *name;
717 isc_time_t filetime;
718 ISC_LINK(dns_include_t) link;
719};
720
721/*
722 * These can be overridden by the -T mkeytimers option on the command
723 * line, so that we can test with shorter periods than specified in
724 * RFC 5011.
725 */
726#define HOUR 3600
727#define DAY (24*HOUR)
728#define MONTH (30*DAY)
729LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_hour = HOUR;
730LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_day = DAY;
731LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_month = MONTH;
732
733#define SEND_BUFFER_SIZE 2048
734
735static void zone_settimer(dns_zone_t *, isc_time_t *);
736static void cancel_refresh(dns_zone_t *);
737static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
738 const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
739static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
740 ISC_FORMAT_PRINTF(3, 4);
741static void dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
742 ISC_FORMAT_PRINTF(3, 4);
743static void queue_xfrin(dns_zone_t *zone);
744static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
745 dns_diff_t *diff, dns_diffop_t op,
746 dns_name_t *name, dns_ttl_t ttl,
747 dns_rdata_t *rdata);
748static void zone_unload(dns_zone_t *zone);
749static void zone_expire(dns_zone_t *zone);
750static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
751static void zone_idetach(dns_zone_t **zonep);
752static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
753 bool dump);
754static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
755static inline void zone_detachdb(dns_zone_t *zone);
756static isc_result_t default_journal(dns_zone_t *zone);
757static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
758static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
759 isc_time_t loadtime, isc_result_t result);
760static void zone_needdump(dns_zone_t *zone, unsigned int delay);
761static void zone_shutdown(isc_task_t *, isc_event_t *);
762static void zone_loaddone(void *arg, isc_result_t result);
763static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
764 isc_time_t loadtime);
765static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
766static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
767static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
768static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
769static isc_result_t zone_send_secureserial(dns_zone_t *zone,
770 uint32_t serial);
771static void refresh_callback(isc_task_t *, isc_event_t *);
772static void stub_callback(isc_task_t *, isc_event_t *);
773static void queue_soa_query(dns_zone_t *zone);
774static void soa_query(isc_task_t *, isc_event_t *);
775static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
776 dns_stub_t *stub);
777static int message_count(dns_message_t *msg, dns_section_t section,
778 dns_rdatatype_t type);
779static void notify_cancel(dns_zone_t *zone);
780static void notify_find_address(dns_notify_t *notify);
781static void notify_send(dns_notify_t *notify);
782static isc_result_t notify_createmessage(dns_zone_t *zone,
783 unsigned int flags,
784 dns_message_t **messagep);
785static void notify_done(isc_task_t *task, isc_event_t *event);
786static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
787static isc_result_t zone_dump(dns_zone_t *, bool);
788static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
789static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
790 dns_zone_t *zone);
791static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
792static void zonemgr_free(dns_zonemgr_t *zmgr);
793static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, bool high,
794 isc_task_t *task, isc_taskaction_t action,
795 void *arg, dns_io_t **iop);
796static void zonemgr_putio(dns_io_t **iop);
797static void zonemgr_cancelio(dns_io_t *io);
798
799static isc_result_t
800zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
801 unsigned int *soacount, uint32_t *serial,
802 uint32_t *refresh, uint32_t *retry,
803 uint32_t *expire, uint32_t *minimum,
804 unsigned int *errors);
805
806static void zone_freedbargs(dns_zone_t *zone);
807static void forward_callback(isc_task_t *task, isc_event_t *event);
808static void zone_saveunique(dns_zone_t *zone, const char *path,
809 const char *templat);
810static void zone_maintenance(dns_zone_t *zone);
811static void zone_notify(dns_zone_t *zone, isc_time_t *now);
812static void dump_done(void *arg, isc_result_t result);
813static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
814 uint16_t keyid,
815 bool deleteit);
816static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
817 dns_dbnode_t *node, dns_name_t *name,
818 dns_diff_t *diff);
819static void zone_rekey(dns_zone_t *zone);
820static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
821static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
822 unsigned int value);
823
824#define ENTER zone_debuglog(zone, me, 1, "enter")
825
826static const unsigned int dbargc_default = 1;
827static const char *dbargv_default[] = { "rbt" };
828
829#define DNS_ZONE_JITTER_ADD(a, b, c) \
830 do { \
831 isc_interval_t _i; \
832 uint32_t _j; \
833 _j = (b) - isc_random_uniform((b)/4); \
834 isc_interval_set(&_i, _j, 0); \
835 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
836 dns_zone_log(zone, ISC_LOG_WARNING, \
837 "epoch approaching: upgrade required: " \
838 "now + %s failed", #b); \
839 isc_interval_set(&_i, _j/2, 0); \
840 (void)isc_time_add((a), &_i, (c)); \
841 } \
842 } while (/*CONSTCOND*/0)
843
844#define DNS_ZONE_TIME_ADD(a, b, c) \
845 do { \
846 isc_interval_t _i; \
847 isc_interval_set(&_i, (b), 0); \
848 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
849 dns_zone_log(zone, ISC_LOG_WARNING, \
850 "epoch approaching: upgrade required: " \
851 "now + %s failed", #b); \
852 isc_interval_set(&_i, (b)/2, 0); \
853 (void)isc_time_add((a), &_i, (c)); \
854 } \
855 } while (/*CONSTCOND*/0)
856
857typedef struct nsec3param nsec3param_t;
858struct nsec3param {
859 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
860 unsigned int length;
861 bool nsec;
862 bool replace;
863 ISC_LINK(nsec3param_t) link;
864};
865typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
866struct np3event {
867 isc_event_t event;
868 nsec3param_t params;
869};
870
871struct ssevent {
872 isc_event_t event;
873 uint32_t serial;
874};
875
876/*%
877 * Increment resolver-related statistics counters. Zone must be locked.
878 */
879static inline void
880inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
881 if (zone->stats != NULL)
882 isc_stats_increment(zone->stats, counter);
883}
884
885/***
886 *** Public functions.
887 ***/
888
889isc_result_t
890dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
891 isc_result_t result;
892 dns_zone_t *zone;
893 isc_time_t now;
894
895 REQUIRE(zonep != NULL && *zonep == NULL);
896 REQUIRE(mctx != NULL);
897
898 TIME_NOW(&now);
899 zone = isc_mem_get(mctx, sizeof(*zone));
900 if (zone == NULL) {
901 return (ISC_R_NOMEMORY);
902 }
903
904 zone->mctx = NULL;
905 isc_mem_attach(mctx, &zone->mctx);
906
907 isc_mutex_init(&zone->lock);
908
909 result = ZONEDB_INITLOCK(&zone->dblock);
910 if (result != ISC_R_SUCCESS) {
911 goto free_mutex;
912 }
913
914 /* XXX MPA check that all elements are initialised */
915#ifdef DNS_ZONE_CHECKLOCK
916 zone->locked = false;
917#endif
918 zone->db = NULL;
919 zone->zmgr = NULL;
920 ISC_LINK_INIT(zone, link);
921 isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
922 zone->irefs = 0;
923 dns_name_init(&zone->origin, NULL);
924 zone->strnamerd = NULL;
925 zone->strname = NULL;
926 zone->strrdclass = NULL;
927 zone->strviewname = NULL;
928 zone->masterfile = NULL;
929 ISC_LIST_INIT(zone->includes);
930 ISC_LIST_INIT(zone->newincludes);
931 zone->nincludes = 0;
932 zone->masterformat = dns_masterformat_none;
933 zone->masterstyle = NULL;
934 zone->keydirectory = NULL;
935 zone->journalsize = -1;
936 zone->journal = NULL;
937 zone->rdclass = dns_rdataclass_none;
938 zone->type = dns_zone_none;
939 zone->flags = 0;
940 zone->options = 0;
941 zone->keyopts = 0;
942 zone->db_argc = 0;
943 zone->db_argv = NULL;
944 isc_time_settoepoch(&zone->expiretime);
945 isc_time_settoepoch(&zone->refreshtime);
946 isc_time_settoepoch(&zone->dumptime);
947 isc_time_settoepoch(&zone->loadtime);
948 zone->notifytime = now;
949 isc_time_settoepoch(&zone->resigntime);
950 isc_time_settoepoch(&zone->keywarntime);
951 isc_time_settoepoch(&zone->signingtime);
952 isc_time_settoepoch(&zone->nsec3chaintime);
953 isc_time_settoepoch(&zone->refreshkeytime);
954 zone->refreshkeyinterval = 0;
955 zone->refreshkeycount = 0;
956 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
957 zone->retry = DNS_ZONE_DEFAULTRETRY;
958 zone->expire = 0;
959 zone->minimum = 0;
960 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
961 zone->minrefresh = DNS_ZONE_MINREFRESH;
962 zone->maxretry = DNS_ZONE_MAXRETRY;
963 zone->minretry = DNS_ZONE_MINRETRY;
964 zone->masters = NULL;
965 zone->masterdscps = NULL;
966 zone->masterkeynames = NULL;
967 zone->mastersok = NULL;
968 zone->masterscnt = 0;
969 zone->curmaster = 0;
970 zone->maxttl = 0;
971 zone->notify = NULL;
972 zone->notifykeynames = NULL;
973 zone->notifydscp = NULL;
974 zone->notifytype = dns_notifytype_yes;
975 zone->notifycnt = 0;
976 zone->task = NULL;
977 zone->loadtask = NULL;
978 zone->update_acl = NULL;
979 zone->forward_acl = NULL;
980 zone->notify_acl = NULL;
981 zone->query_acl = NULL;
982 zone->queryon_acl = NULL;
983 zone->xfr_acl = NULL;
984 zone->update_disabled = false;
985 zone->zero_no_soa_ttl = true;
986 zone->check_names = dns_severity_ignore;
987 zone->request = NULL;
988 zone->lctx = NULL;
989 zone->readio = NULL;
990 zone->dctx = NULL;
991 zone->writeio = NULL;
992 zone->timer = NULL;
993 zone->idlein = DNS_DEFAULT_IDLEIN;
994 zone->idleout = DNS_DEFAULT_IDLEOUT;
995 zone->log_key_expired_timer = 0;
996 ISC_LIST_INIT(zone->notifies);
997 isc_sockaddr_any(&zone->notifysrc4);
998 isc_sockaddr_any6(&zone->notifysrc6);
999 isc_sockaddr_any(&zone->xfrsource4);
1000 isc_sockaddr_any6(&zone->xfrsource6);
1001 isc_sockaddr_any(&zone->altxfrsource4);
1002 isc_sockaddr_any6(&zone->altxfrsource6);
1003 zone->notifysrc4dscp = -1;
1004 zone->notifysrc6dscp = -1;
1005 zone->xfrsource4dscp = -1;
1006 zone->xfrsource6dscp = -1;
1007 zone->altxfrsource4dscp = -1;
1008 zone->altxfrsource6dscp = -1;
1009 zone->xfr = NULL;
1010 zone->tsigkey = NULL;
1011 zone->maxxfrin = MAX_XFER_TIME;
1012 zone->maxxfrout = MAX_XFER_TIME;
1013 zone->ssutable = NULL;
1014 zone->sigvalidityinterval = 30 * 24 * 3600;
1015 zone->keyvalidityinterval = 0;
1016 zone->sigresigninginterval = 7 * 24 * 3600;
1017 zone->view = NULL;
1018 zone->prev_view = NULL;
1019 zone->checkmx = NULL;
1020 zone->checksrv = NULL;
1021 zone->checkns = NULL;
1022 ISC_LINK_INIT(zone, statelink);
1023 zone->statelist = NULL;
1024 zone->stats = NULL;
1025 zone->requeststats_on = false;
1026 zone->statlevel = dns_zonestat_none;
1027 zone->requeststats = NULL;
1028 zone->rcvquerystats = NULL;
1029 zone->notifydelay = 5;
1030 zone->isself = NULL;
1031 zone->isselfarg = NULL;
1032 ISC_LIST_INIT(zone->signing);
1033 ISC_LIST_INIT(zone->nsec3chain);
1034 ISC_LIST_INIT(zone->setnsec3param_queue);
1035 zone->signatures = 10;
1036 zone->nodes = 100;
1037 zone->privatetype = (dns_rdatatype_t)0xffffU;
1038 zone->added = false;
1039 zone->automatic = false;
1040 zone->rpzs = NULL;
1041 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1042
1043 zone->catzs = NULL;
1044 zone->parentcatz = NULL;
1045
1046 ISC_LIST_INIT(zone->forwards);
1047 zone->raw = NULL;
1048 zone->secure = NULL;
1049 zone->sourceserial = 0;
1050 zone->sourceserialset = false;
1051 zone->requestixfr = true;
1052 zone->requestexpire = true;
1053 ISC_LIST_INIT(zone->rss_events);
1054 zone->rss_db = NULL;
1055 zone->rss_raw = NULL;
1056 zone->rss_newver = NULL;
1057 zone->rss_oldver = NULL;
1058 zone->rss_event = NULL;
1059 zone->rss_state = NULL;
1060 zone->updatemethod = dns_updatemethod_increment;
1061 zone->maxrecords = 0U;
1062
1063 zone->magic = ZONE_MAGIC;
1064
1065 zone->gluecachestats = NULL;
1066 result = isc_stats_create(mctx, &zone->gluecachestats,
1067 dns_gluecachestatscounter_max);
1068 if (result != ISC_R_SUCCESS) {
1069 goto free_erefs;
1070 }
1071
1072 /* Must be after magic is set. */
1073 result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1074 if (result != ISC_R_SUCCESS) {
1075 goto free_stats;
1076 }
1077
1078 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1079 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
1080 NULL, NULL);
1081 *zonep = zone;
1082 return (ISC_R_SUCCESS);
1083
1084 free_stats:
1085 if (zone->gluecachestats != NULL)
1086 isc_stats_detach(&zone->gluecachestats);
1087
1088 free_erefs:
1089 INSIST(isc_refcount_decrement(&zone->erefs) > 0);
1090 isc_refcount_destroy(&zone->erefs);
1091
1092 ZONEDB_DESTROYLOCK(&zone->dblock);
1093
1094 free_mutex:
1095 isc_mutex_destroy(&zone->lock);
1096
1097 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1098 return (result);
1099}
1100
1101/*
1102 * Free a zone. Because we require that there be no more
1103 * outstanding events or references, no locking is necessary.
1104 */
1105static void
1106zone_free(dns_zone_t *zone) {
1107 isc_mem_t *mctx = NULL;
1108 dns_signing_t *signing;
1109 dns_nsec3chain_t *nsec3chain;
1110 isc_event_t *setnsec3param_event;
1111 dns_include_t *include;
1112
1113 REQUIRE(DNS_ZONE_VALID(zone));
1114 REQUIRE(isc_refcount_current(&zone->erefs) == 0);
1115 REQUIRE(zone->irefs == 0);
1116 REQUIRE(!LOCKED_ZONE(zone));
1117 REQUIRE(zone->timer == NULL);
1118 REQUIRE(zone->zmgr == NULL);
1119
1120 /*
1121 * Managed objects. Order is important.
1122 */
1123 if (zone->request != NULL) {
1124 dns_request_destroy(&zone->request); /* XXXMPA */
1125 }
1126 INSIST(zone->readio == NULL);
1127 INSIST(zone->statelist == NULL);
1128 INSIST(zone->writeio == NULL);
1129
1130 if (zone->task != NULL) {
1131 isc_task_detach(&zone->task);
1132 }
1133 if (zone->loadtask != NULL) {
1134 isc_task_detach(&zone->loadtask);
1135 }
1136 if (zone->view != NULL) {
1137 dns_view_weakdetach(&zone->view);
1138 }
1139 if (zone->prev_view != NULL) {
1140 dns_view_weakdetach(&zone->prev_view);
1141 }
1142
1143 /* Unmanaged objects */
1144 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1145 setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1146 ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
1147 ev_link);
1148 isc_event_free(&setnsec3param_event);
1149 }
1150 for (signing = ISC_LIST_HEAD(zone->signing);
1151 signing != NULL;
1152 signing = ISC_LIST_HEAD(zone->signing)) {
1153 ISC_LIST_UNLINK(zone->signing, signing, link);
1154 dns_db_detach(&signing->db);
1155 dns_dbiterator_destroy(&signing->dbiterator);
1156 isc_mem_put(zone->mctx, signing, sizeof *signing);
1157 }
1158 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
1159 nsec3chain != NULL;
1160 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
1161 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1162 dns_db_detach(&nsec3chain->db);
1163 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1164 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1165 }
1166 for (include = ISC_LIST_HEAD(zone->includes);
1167 include != NULL;
1168 include = ISC_LIST_HEAD(zone->includes)) {
1169 ISC_LIST_UNLINK(zone->includes, include, link);
1170 isc_mem_free(zone->mctx, include->name);
1171 isc_mem_put(zone->mctx, include, sizeof *include);
1172 }
1173 for (include = ISC_LIST_HEAD(zone->newincludes);
1174 include != NULL;
1175 include = ISC_LIST_HEAD(zone->newincludes)) {
1176 ISC_LIST_UNLINK(zone->newincludes, include, link);
1177 isc_mem_free(zone->mctx, include->name);
1178 isc_mem_put(zone->mctx, include, sizeof *include);
1179 }
1180 if (zone->masterfile != NULL) {
1181 isc_mem_free(zone->mctx, zone->masterfile);
1182 }
1183 zone->masterfile = NULL;
1184 if (zone->keydirectory != NULL) {
1185 isc_mem_free(zone->mctx, zone->keydirectory);
1186 }
1187 zone->keydirectory = NULL;
1188 zone->journalsize = -1;
1189 if (zone->journal != NULL) {
1190 isc_mem_free(zone->mctx, zone->journal);
1191 }
1192 zone->journal = NULL;
1193 if (zone->stats != NULL) {
1194 isc_stats_detach(&zone->stats);
1195 }
1196 if (zone->requeststats != NULL) {
1197 isc_stats_detach(&zone->requeststats);
1198 }
1199 if (zone->rcvquerystats != NULL){
1200 dns_stats_detach(&zone->rcvquerystats);
1201 }
1202 if (zone->db != NULL) {
1203 zone_detachdb(zone);
1204 }
1205 if (zone->rpzs != NULL) {
1206 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1207 dns_rpz_detach_rpzs(&zone->rpzs);
1208 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1209 }
1210 if (zone->catzs != NULL) {
1211 dns_catz_catzs_detach(&zone->catzs);
1212 }
1213 zone_freedbargs(zone);
1214 RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL,
1215 NULL, 0) == ISC_R_SUCCESS);
1216 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
1217 zone->check_names = dns_severity_ignore;
1218 if (zone->update_acl != NULL) {
1219 dns_acl_detach(&zone->update_acl);
1220 }
1221 if (zone->forward_acl != NULL) {
1222 dns_acl_detach(&zone->forward_acl);
1223 }
1224 if (zone->notify_acl != NULL) {
1225 dns_acl_detach(&zone->notify_acl);
1226 }
1227 if (zone->query_acl != NULL) {
1228 dns_acl_detach(&zone->query_acl);
1229 }
1230 if (zone->queryon_acl != NULL) {
1231 dns_acl_detach(&zone->queryon_acl);
1232 }
1233 if (zone->xfr_acl != NULL) {
1234 dns_acl_detach(&zone->xfr_acl);
1235 }
1236 if (dns_name_dynamic(&zone->origin)) {
1237 dns_name_free(&zone->origin, zone->mctx);
1238 }
1239 if (zone->strnamerd != NULL) {
1240 isc_mem_free(zone->mctx, zone->strnamerd);
1241 }
1242 if (zone->strname != NULL) {
1243 isc_mem_free(zone->mctx, zone->strname);
1244 }
1245 if (zone->strrdclass != NULL) {
1246 isc_mem_free(zone->mctx, zone->strrdclass);
1247 }
1248 if (zone->strviewname != NULL) {
1249 isc_mem_free(zone->mctx, zone->strviewname);
1250 }
1251 if (zone->ssutable != NULL) {
1252 dns_ssutable_detach(&zone->ssutable);
1253 }
1254 if (zone->gluecachestats != NULL) {
1255 isc_stats_detach(&zone->gluecachestats);
1256 }
1257
1258 /* last stuff */
1259 ZONEDB_DESTROYLOCK(&zone->dblock);
1260 isc_mutex_destroy(&zone->lock);
1261 zone->magic = 0;
1262 mctx = zone->mctx;
1263 isc_mem_put(mctx, zone, sizeof(*zone));
1264 isc_mem_detach(&mctx);
1265}
1266
1267/*
1268 * Returns true iff this the signed side of an inline-signing zone.
1269 * Caller should hold zone lock.
1270 */
1271static inline bool
1272inline_secure(dns_zone_t *zone) {
1273 REQUIRE(DNS_ZONE_VALID(zone));
1274 if (zone->raw != NULL)
1275 return (true);
1276 return (false);
1277}
1278
1279/*
1280 * Returns true iff this the unsigned side of an inline-signing zone
1281 * Caller should hold zone lock.
1282 */
1283static inline bool
1284inline_raw(dns_zone_t *zone) {
1285 REQUIRE(DNS_ZONE_VALID(zone));
1286 if (zone->secure != NULL)
1287 return (true);
1288 return (false);
1289}
1290
1291/*
1292 * Single shot.
1293 */
1294void
1295dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1296 char namebuf[1024];
1297
1298 REQUIRE(DNS_ZONE_VALID(zone));
1299 REQUIRE(rdclass != dns_rdataclass_none);
1300
1301 /*
1302 * Test and set.
1303 */
1304 LOCK_ZONE(zone);
1305 INSIST(zone != zone->raw);
1306 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1307 zone->rdclass == rdclass);
1308 zone->rdclass = rdclass;
1309
1310 if (zone->strnamerd != NULL)
1311 isc_mem_free(zone->mctx, zone->strnamerd);
1312 if (zone->strrdclass != NULL)
1313 isc_mem_free(zone->mctx, zone->strrdclass);
1314
1315 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1316 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1317 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1318 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1319
1320 if (inline_secure(zone))
1321 dns_zone_setclass(zone->raw, rdclass);
1322 UNLOCK_ZONE(zone);
1323}
1324
1325dns_rdataclass_t
1326dns_zone_getclass(dns_zone_t *zone) {
1327 REQUIRE(DNS_ZONE_VALID(zone));
1328
1329 return (zone->rdclass);
1330}
1331
1332void
1333dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1334 REQUIRE(DNS_ZONE_VALID(zone));
1335
1336 LOCK_ZONE(zone);
1337 zone->notifytype = notifytype;
1338 UNLOCK_ZONE(zone);
1339}
1340
1341isc_result_t
1342dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1343 isc_result_t result;
1344 unsigned int soacount;
1345
1346 REQUIRE(DNS_ZONE_VALID(zone));
1347 REQUIRE(serialp != NULL);
1348
1349 LOCK_ZONE(zone);
1350 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1351 if (zone->db != NULL) {
1352 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1353 serialp, NULL, NULL, NULL, NULL,
1354 NULL);
1355 if (result == ISC_R_SUCCESS && soacount == 0)
1356 result = ISC_R_FAILURE;
1357 } else
1358 result = DNS_R_NOTLOADED;
1359 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1360 UNLOCK_ZONE(zone);
1361
1362 return (result);
1363}
1364
1365/*
1366 * Single shot.
1367 */
1368void
1369dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1370 char namebuf[1024];
1371
1372 REQUIRE(DNS_ZONE_VALID(zone));
1373 REQUIRE(type != dns_zone_none);
1374
1375 /*
1376 * Test and set.
1377 */
1378 LOCK_ZONE(zone);
1379 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1380 zone->type = type;
1381
1382 if (zone->strnamerd != NULL)
1383 isc_mem_free(zone->mctx, zone->strnamerd);
1384
1385 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1386 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1387 UNLOCK_ZONE(zone);
1388}
1389
1390static void
1391zone_freedbargs(dns_zone_t *zone) {
1392 unsigned int i;
1393
1394 /* Free the old database argument list. */
1395 if (zone->db_argv != NULL) {
1396 for (i = 0; i < zone->db_argc; i++)
1397 isc_mem_free(zone->mctx, zone->db_argv[i]);
1398 isc_mem_put(zone->mctx, zone->db_argv,
1399 zone->db_argc * sizeof(*zone->db_argv));
1400 }
1401 zone->db_argc = 0;
1402 zone->db_argv = NULL;
1403}
1404
1405isc_result_t
1406dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1407 size_t size = 0;
1408 unsigned int i;
1409 isc_result_t result = ISC_R_SUCCESS;
1410 void *mem;
1411 char **tmp, *tmp2, *base;
1412
1413 REQUIRE(DNS_ZONE_VALID(zone));
1414 REQUIRE(argv != NULL && *argv == NULL);
1415
1416 LOCK_ZONE(zone);
1417 size = (zone->db_argc + 1) * sizeof(char *);
1418 for (i = 0; i < zone->db_argc; i++)
1419 size += strlen(zone->db_argv[i]) + 1;
1420 mem = isc_mem_allocate(mctx, size);
1421 if (mem != NULL) {
1422 tmp = mem;
1423 tmp2 = mem;
1424 base = mem;
1425 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1426 for (i = 0; i < zone->db_argc; i++) {
1427 *tmp++ = tmp2;
1428 strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1429 tmp2 += strlen(tmp2) + 1;
1430 }
1431 *tmp = NULL;
1432 } else
1433 result = ISC_R_NOMEMORY;
1434 UNLOCK_ZONE(zone);
1435 *argv = mem;
1436 return (result);
1437}
1438
1439isc_result_t
1440dns_zone_setdbtype(dns_zone_t *zone,
1441 unsigned int dbargc, const char * const *dbargv)
1442{
1443 isc_result_t result = ISC_R_SUCCESS;
1444 char **argv = NULL;
1445 unsigned int i;
1446
1447 REQUIRE(DNS_ZONE_VALID(zone));
1448 REQUIRE(dbargc >= 1);
1449 REQUIRE(dbargv != NULL);
1450
1451 LOCK_ZONE(zone);
1452
1453 /* Set up a new database argument list. */
1454 argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1455 if (argv == NULL) {
1456 goto nomem;
1457 }
1458 for (i = 0; i < dbargc; i++) {
1459 argv[i] = NULL;
1460 }
1461 for (i = 0; i < dbargc; i++) {
1462 argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1463 if (argv[i] == NULL)
1464 goto nomem;
1465 }
1466
1467 /* Free the old list. */
1468 zone_freedbargs(zone);
1469
1470 zone->db_argc = dbargc;
1471 zone->db_argv = argv;
1472 result = ISC_R_SUCCESS;
1473 goto unlock;
1474
1475 nomem:
1476 if (argv != NULL) {
1477 for (i = 0; i < dbargc; i++) {
1478 if (argv[i] != NULL) {
1479 isc_mem_free(zone->mctx, argv[i]);
1480 }
1481 }
1482 isc_mem_put(zone->mctx, argv, dbargc * sizeof(*argv));
1483 }
1484 result = ISC_R_NOMEMORY;
1485
1486 unlock:
1487 UNLOCK_ZONE(zone);
1488 return (result);
1489}
1490
1491static void
1492dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1493 char namebuf[1024];
1494
1495 if (zone->prev_view == NULL && zone->view != NULL) {
1496 dns_view_weakattach(zone->view, &zone->prev_view);
1497 }
1498
1499 INSIST(zone != zone->raw);
1500 if (zone->view != NULL) {
1501 dns_view_weakdetach(&zone->view);
1502 }
1503 dns_view_weakattach(view, &zone->view);
1504
1505 if (zone->strviewname != NULL) {
1506 isc_mem_free(zone->mctx, zone->strviewname);
1507 }
1508 if (zone->strnamerd != NULL) {
1509 isc_mem_free(zone->mctx, zone->strnamerd);
1510 }
1511
1512 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1513 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1514 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1515 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1516
1517 if (inline_secure(zone)) {
1518 dns_zone_setview(zone->raw, view);
1519 }
1520}
1521
1522void
1523dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1524 REQUIRE(DNS_ZONE_VALID(zone));
1525
1526 LOCK_ZONE(zone);
1527 dns_zone_setview_helper(zone, view);
1528 UNLOCK_ZONE(zone);
1529}
1530
1531dns_view_t *
1532dns_zone_getview(dns_zone_t *zone) {
1533 REQUIRE(DNS_ZONE_VALID(zone));
1534
1535 return (zone->view);
1536}
1537
1538void
1539dns_zone_setviewcommit(dns_zone_t *zone) {
1540 REQUIRE(DNS_ZONE_VALID(zone));
1541
1542 LOCK_ZONE(zone);
1543 if (zone->prev_view != NULL)
1544 dns_view_weakdetach(&zone->prev_view);
1545 UNLOCK_ZONE(zone);
1546}
1547
1548void
1549dns_zone_setviewrevert(dns_zone_t *zone) {
1550 REQUIRE(DNS_ZONE_VALID(zone));
1551
1552 LOCK_ZONE(zone);
1553 if (zone->prev_view != NULL) {
1554 dns_zone_setview_helper(zone, zone->prev_view);
1555 dns_view_weakdetach(&zone->prev_view);
1556 }
1557 UNLOCK_ZONE(zone);
1558}
1559
1560isc_result_t
1561dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1562 isc_result_t result;
1563 char namebuf[1024];
1564
1565 REQUIRE(DNS_ZONE_VALID(zone));
1566 REQUIRE(origin != NULL);
1567
1568 LOCK_ZONE(zone);
1569 INSIST(zone != zone->raw);
1570 if (dns_name_dynamic(&zone->origin)) {
1571 dns_name_free(&zone->origin, zone->mctx);
1572 dns_name_init(&zone->origin, NULL);
1573 }
1574 result = dns_name_dup(origin, zone->mctx, &zone->origin);
1575
1576 if (zone->strnamerd != NULL)
1577 isc_mem_free(zone->mctx, zone->strnamerd);
1578 if (zone->strname != NULL)
1579 isc_mem_free(zone->mctx, zone->strname);
1580
1581 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1582 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1583 zone_name_tostr(zone, namebuf, sizeof namebuf);
1584 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1585
1586 if (result == ISC_R_SUCCESS && inline_secure(zone))
1587 result = dns_zone_setorigin(zone->raw, origin);
1588 UNLOCK_ZONE(zone);
1589 return (result);
1590}
1591
1592static isc_result_t
1593dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1594 char *copy;
1595
1596 if (value != NULL) {
1597 copy = isc_mem_strdup(zone->mctx, value);
1598 if (copy == NULL)
1599 return (ISC_R_NOMEMORY);
1600 } else {
1601 copy = NULL;
1602 }
1603
1604 if (*field != NULL)
1605 isc_mem_free(zone->mctx, *field);
1606
1607 *field = copy;
1608 return (ISC_R_SUCCESS);
1609}
1610
1611isc_result_t
1612dns_zone_setfile(dns_zone_t *zone, const char *file,
1613 dns_masterformat_t format,
1614 const dns_master_style_t *style)
1615{
1616 isc_result_t result = ISC_R_SUCCESS;
1617
1618 REQUIRE(DNS_ZONE_VALID(zone));
1619
1620 LOCK_ZONE(zone);
1621 result = dns_zone_setstring(zone, &zone->masterfile, file);
1622 if (result == ISC_R_SUCCESS) {
1623 zone->masterformat = format;
1624 if (format == dns_masterformat_text)
1625 zone->masterstyle = style;
1626 result = default_journal(zone);
1627 }
1628 UNLOCK_ZONE(zone);
1629
1630 return (result);
1631}
1632
1633const char *
1634dns_zone_getfile(dns_zone_t *zone) {
1635 REQUIRE(DNS_ZONE_VALID(zone));
1636
1637 return (zone->masterfile);
1638}
1639
1640dns_ttl_t
1641dns_zone_getmaxttl(dns_zone_t *zone) {
1642 REQUIRE(DNS_ZONE_VALID(zone));
1643
1644 return (zone->maxttl);
1645}
1646
1647void
1648dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1649 REQUIRE(DNS_ZONE_VALID(zone));
1650
1651 LOCK_ZONE(zone);
1652 if (maxttl != 0)
1653 zone->options |= DNS_ZONEOPT_CHECKTTL;
1654 else
1655 zone->options &= ~DNS_ZONEOPT_CHECKTTL;
1656 zone->maxttl = maxttl;
1657 UNLOCK_ZONE(zone);
1658
1659 return;
1660}
1661
1662static isc_result_t
1663default_journal(dns_zone_t *zone) {
1664 isc_result_t result;
1665 char *journal;
1666
1667 REQUIRE(DNS_ZONE_VALID(zone));
1668 REQUIRE(LOCKED_ZONE(zone));
1669
1670 if (zone->masterfile != NULL) {
1671 /* Calculate string length including '\0'. */
1672 int len = strlen(zone->masterfile) + sizeof(".jnl");
1673 journal = isc_mem_allocate(zone->mctx, len);
1674 if (journal == NULL)
1675 return (ISC_R_NOMEMORY);
1676 strlcpy(journal, zone->masterfile, len);
1677 strlcat(journal, ".jnl", len);
1678 } else {
1679 journal = NULL;
1680 }
1681 result = dns_zone_setstring(zone, &zone->journal, journal);
1682 if (journal != NULL)
1683 isc_mem_free(zone->mctx, journal);
1684 return (result);
1685}
1686
1687isc_result_t
1688dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1689 isc_result_t result = ISC_R_SUCCESS;
1690
1691 REQUIRE(DNS_ZONE_VALID(zone));
1692
1693 LOCK_ZONE(zone);
1694 result = dns_zone_setstring(zone, &zone->journal, myjournal);
1695 UNLOCK_ZONE(zone);
1696
1697 return (result);
1698}
1699
1700char *
1701dns_zone_getjournal(dns_zone_t *zone) {
1702 REQUIRE(DNS_ZONE_VALID(zone));
1703
1704 return (zone->journal);
1705}
1706
1707/*
1708 * Return true iff the zone is "dynamic", in the sense that the zone's
1709 * master file (if any) is written by the server, rather than being
1710 * updated manually and read by the server.
1711 *
1712 * This is true for slave zones, mirror zones, stub zones, key zones,
1713 * and zones that allow dynamic updates either by having an update
1714 * policy ("ssutable") or an "allow-update" ACL with a value other than
1715 * exactly "{ none; }".
1716 */
1717bool
1718dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1719 REQUIRE(DNS_ZONE_VALID(zone));
1720
1721 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
1722 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1723 (zone->type == dns_zone_redirect && zone->masters != NULL))
1724 return (true);
1725
1726 /* Inline zones are always dynamic. */
1727 if (zone->type == dns_zone_master && zone->raw != NULL)
1728 return (true);
1729
1730 /* If !ignore_freeze, we need check whether updates are disabled. */
1731 if (zone->type == dns_zone_master &&
1732 (!zone->update_disabled || ignore_freeze) &&
1733 ((zone->ssutable != NULL) ||
1734 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1735 return (true);
1736
1737 return (false);
1738
1739}
1740
1741/*
1742 * Set the response policy index and information for a zone.
1743 */
1744isc_result_t
1745dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1746 dns_rpz_num_t rpz_num)
1747{
1748 /*
1749 * Only RBTDB zones can be used for response policy zones,
1750 * because only they have the code to load the create the summary data.
1751 * Only zones that are loaded instead of mmap()ed create the
1752 * summary data and so can be policy zones.
1753 */
1754 if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1755 strcmp(zone->db_argv[0], "rbt64") != 0)
1756 return (ISC_R_NOTIMPLEMENTED);
1757 if (zone->masterformat == dns_masterformat_map)
1758 return (ISC_R_NOTIMPLEMENTED);
1759
1760 /*
1761 * This must happen only once or be redundant.
1762 */
1763 LOCK_ZONE(zone);
1764 if (zone->rpzs != NULL) {
1765 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1766 } else {
1767 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1768 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1769 zone->rpz_num = rpz_num;
1770 }
1771 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1772 UNLOCK_ZONE(zone);
1773
1774 return (ISC_R_SUCCESS);
1775}
1776
1777dns_rpz_num_t
1778dns_zone_get_rpz_num(dns_zone_t *zone) {
1779 return (zone->rpz_num);
1780}
1781
1782/*
1783 * If a zone is a response policy zone, mark its new database.
1784 */
1785void
1786dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1787 isc_result_t result;
1788 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1789 return;
1790 }
1791 REQUIRE(zone->rpzs != NULL);
1792 result = dns_db_updatenotify_register(db,
1793 dns_rpz_dbupdate_callback,
1794 zone->rpzs->zones[zone->rpz_num]);
1795 REQUIRE(result == ISC_R_SUCCESS);
1796}
1797
1798static void
1799dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1800 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1801 return;
1802 }
1803 REQUIRE(zone->rpzs != NULL);
1804 (void) dns_db_updatenotify_unregister(db,
1805 dns_rpz_dbupdate_callback,
1806 zone->rpzs->zones[zone->rpz_num]);
1807}
1808
1809void
1810dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1811 REQUIRE(DNS_ZONE_VALID(zone));
1812 REQUIRE(catzs != NULL);
1813
1814 LOCK_ZONE(zone);
1815 INSIST(zone->catzs == NULL || zone->catzs == catzs);
1816 dns_catz_catzs_set_view(catzs, zone->view);
1817 if (zone->catzs == NULL) {
1818 dns_catz_catzs_attach(catzs, &zone->catzs);
1819 }
1820 UNLOCK_ZONE(zone);
1821}
1822
1823/*
1824 * If a zone is a catalog zone, attach it to update notification in database.
1825 */
1826void
1827dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1828 REQUIRE(DNS_ZONE_VALID(zone));
1829 REQUIRE(db != NULL);
1830
1831 if (zone->catzs != NULL) {
1832 dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
1833 zone->catzs);
1834 }
1835}
1836
1837static void
1838dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1839 REQUIRE(DNS_ZONE_VALID(zone));
1840 REQUIRE(db != NULL);
1841
1842 if (zone->catzs != NULL) {
1843 dns_db_updatenotify_unregister(db, dns_catz_dbupdate_callback,
1844 zone->catzs);
1845 }
1846}
1847
1848/*
1849 * Set catalog zone ownership of the zone
1850 */
1851void
1852dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
1853 REQUIRE(DNS_ZONE_VALID(zone));
1854 REQUIRE(catz != NULL);
1855 LOCK_ZONE(zone);
1856 INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
1857 zone->parentcatz = catz;
1858 UNLOCK_ZONE(zone);
1859}
1860
1861dns_catz_zone_t *
1862dns_zone_get_parentcatz(const dns_zone_t *zone) {
1863 REQUIRE(DNS_ZONE_VALID(zone));
1864 return (zone->parentcatz);
1865}
1866
1867
1868static bool
1869zone_touched(dns_zone_t *zone) {
1870 isc_result_t result;
1871 isc_time_t modtime;
1872 dns_include_t *include;
1873
1874 REQUIRE(DNS_ZONE_VALID(zone));
1875
1876 result = isc_file_getmodtime(zone->masterfile, &modtime);
1877 if (result != ISC_R_SUCCESS ||
1878 isc_time_compare(&modtime, &zone->loadtime) > 0)
1879 return (true);
1880
1881 for (include = ISC_LIST_HEAD(zone->includes);
1882 include != NULL;
1883 include = ISC_LIST_NEXT(include, link))
1884 {
1885 result = isc_file_getmodtime(include->name, &modtime);
1886 if (result != ISC_R_SUCCESS ||
1887 isc_time_compare(&modtime, &include->filetime) > 0)
1888 return (true);
1889 }
1890
1891 return (false);
1892}
1893
1894/*
1895 * Note: when dealing with inline-signed zones, external callers will always
1896 * call zone_load() for the secure zone; zone_load() calls itself recursively
1897 * in order to load the raw zone.
1898 */
1899static isc_result_t
1900zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
1901 isc_result_t result;
1902 isc_time_t now;
1903 isc_time_t loadtime;
1904 dns_db_t *db = NULL;
1905 bool rbt, hasraw;
1906
1907 REQUIRE(DNS_ZONE_VALID(zone));
1908
1909 if (!locked)
1910 LOCK_ZONE(zone);
1911
1912 INSIST(zone != zone->raw);
1913 hasraw = inline_secure(zone);
1914 if (hasraw) {
1915 /*
1916 * We are trying to load an inline-signed zone. First call
1917 * self recursively to try loading the raw version of the zone.
1918 * Assuming the raw zone file is readable, there are two
1919 * possibilities:
1920 *
1921 * a) the raw zone was not yet loaded and thus it will be
1922 * loaded now, synchronously; if this succeeds, a
1923 * subsequent attempt to load the signed zone file will
1924 * take place and thus zone_postload() will be called
1925 * twice: first for the raw zone and then for the secure
1926 * zone; the latter call will take care of syncing the raw
1927 * version with the secure version,
1928 *
1929 * b) the raw zone was already loaded and we are trying to
1930 * reload it, which will happen asynchronously; this means
1931 * zone_postload() will only be called for the raw zone
1932 * because "result" returned by the zone_load() call below
1933 * will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
1934 * zone_postload() called for the raw zone will take care
1935 * of syncing the raw version with the secure version.
1936 */
1937 result = zone_load(zone->raw, flags, false);
1938 if (result != ISC_R_SUCCESS) {
1939 if (!locked)
1940 UNLOCK_ZONE(zone);
1941 return(result);
1942 }
1943 LOCK_ZONE(zone->raw);
1944 }
1945
1946 TIME_NOW(&now);
1947
1948 INSIST(zone->type != dns_zone_none);
1949
1950 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1951 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1952 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1953 result = DNS_R_CONTINUE;
1954 goto cleanup;
1955 }
1956
1957 INSIST(zone->db_argc >= 1);
1958
1959 rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1960 strcmp(zone->db_argv[0], "rbt64") == 0;
1961
1962 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1963 /*
1964 * The zone has no master file configured.
1965 */
1966 result = ISC_R_SUCCESS;
1967 goto cleanup;
1968 }
1969
1970 if (zone->db != NULL && dns_zone_isdynamic(zone, false)) {
1971 /*
1972 * This is a slave, stub, or dynamically updated
1973 * zone being reloaded. Do nothing - the database
1974 * we already have is guaranteed to be up-to-date.
1975 */
1976 if (zone->type == dns_zone_master && !hasraw)
1977 result = DNS_R_DYNAMIC;
1978 else
1979 result = ISC_R_SUCCESS;
1980 goto cleanup;
1981 }
1982
1983 /*
1984 * Store the current time before the zone is loaded, so that if the
1985 * file changes between the time of the load and the time that
1986 * zone->loadtime is set, then the file will still be reloaded
1987 * the next time dns_zone_load is called.
1988 */
1989 TIME_NOW(&loadtime);
1990
1991 /*
1992 * Don't do the load if the file that stores the zone is older
1993 * than the last time the zone was loaded. If the zone has not
1994 * been loaded yet, zone->loadtime will be the epoch.
1995 */
1996 if (zone->masterfile != NULL) {
1997 isc_time_t filetime;
1998
1999 /*
2000 * The file is already loaded. If we are just doing a
2001 * "rndc reconfig", we are done.
2002 */
2003 if (!isc_time_isepoch(&zone->loadtime) &&
2004 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
2005 result = ISC_R_SUCCESS;
2006 goto cleanup;
2007 }
2008
2009 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2010 !zone_touched(zone))
2011 {
2012 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2013 ISC_LOG_DEBUG(1),
2014 "skipping load: master file "
2015 "older than last load");
2016 result = DNS_R_UPTODATE;
2017 goto cleanup;
2018 }
2019
2020 /*
2021 * If the file modification time is in the past
2022 * set loadtime to that value.
2023 */
2024 result = isc_file_getmodtime(zone->masterfile, &filetime);
2025 if (result == ISC_R_SUCCESS &&
2026 isc_time_compare(&loadtime, &filetime) > 0)
2027 loadtime = filetime;
2028 }
2029
2030 /*
2031 * Built in zones (with the exception of empty zones) don't need
2032 * to be reloaded.
2033 */
2034 if (zone->type == dns_zone_master &&
2035 strcmp(zone->db_argv[0], "_builtin") == 0 &&
2036 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2037 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2038 result = ISC_R_SUCCESS;
2039 goto cleanup;
2040 }
2041
2042 /*
2043 * Zones associated with a DLZ don't need to be loaded either,
2044 * but we need to associate the database with the zone object.
2045 */
2046 if (strcmp(zone->db_argv[0], "dlz") == 0) {
2047 dns_dlzdb_t *dlzdb;
2048 dns_dlzfindzone_t findzone;
2049
2050 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2051 dlzdb != NULL;
2052 dlzdb = ISC_LIST_NEXT(dlzdb, link))
2053 {
2054 INSIST(DNS_DLZ_VALID(dlzdb));
2055 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0)
2056 break;
2057 }
2058
2059 if (dlzdb == NULL) {
2060 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2061 ISC_LOG_ERROR,
2062 "DLZ %s does not exist or is set "
2063 "to 'search yes;'", zone->db_argv[1]);
2064 result = ISC_R_NOTFOUND;
2065 goto cleanup;
2066 }
2067
2068 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2069 /* ask SDLZ driver if the zone is supported */
2070 findzone = dlzdb->implementation->methods->findzone;
2071 result = (*findzone)(dlzdb->implementation->driverarg,
2072 dlzdb->dbdata, dlzdb->mctx,
2073 zone->view->rdclass, &zone->origin,
2074 NULL, NULL, &db);
2075 if (result != ISC_R_NOTFOUND) {
2076 if (zone->db != NULL)
2077 zone_detachdb(zone);
2078 zone_attachdb(zone, db);
2079 dns_db_detach(&db);
2080 result = ISC_R_SUCCESS;
2081 }
2082 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2083
2084 if (result == ISC_R_SUCCESS) {
2085 if (dlzdb->configure_callback == NULL)
2086 goto cleanup;
2087
2088 result = (*dlzdb->configure_callback)(zone->view,
2089 dlzdb, zone);
2090 if (result != ISC_R_SUCCESS)
2091 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2092 ISC_LOG_ERROR,
2093 "DLZ configuration callback: %s",
2094 isc_result_totext(result));
2095 }
2096 goto cleanup;
2097 }
2098
2099 if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2100 zone->type == dns_zone_stub ||
2101 (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
2102 rbt) {
2103 if (zone->masterfile == NULL ||
2104 !isc_file_exists(zone->masterfile)) {
2105 if (zone->masterfile != NULL) {
2106 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2107 ISC_LOG_DEBUG(1),
2108 "no master file");
2109 }
2110 zone->refreshtime = now;
2111 if (zone->task != NULL)
2112 zone_settimer(zone, &now);
2113 result = ISC_R_SUCCESS;
2114 goto cleanup;
2115 }
2116 }
2117
2118 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2119 ISC_LOG_DEBUG(1), "starting load");
2120
2121 result = dns_db_create(zone->mctx, zone->db_argv[0],
2122 &zone->origin, (zone->type == dns_zone_stub) ?
2123 dns_dbtype_stub : dns_dbtype_zone,
2124 zone->rdclass,
2125 zone->db_argc - 1, zone->db_argv + 1,
2126 &db);
2127
2128 if (result != ISC_R_SUCCESS) {
2129 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2130 "loading zone: creating database: %s",
2131 isc_result_totext(result));
2132 goto cleanup;
2133 }
2134 dns_db_settask(db, zone->task);
2135
2136 if (zone->type == dns_zone_master || zone->type == dns_zone_slave ||
2137 zone->type == dns_zone_mirror)
2138 {
2139 result = dns_db_setgluecachestats(db, zone->gluecachestats);
2140 if (result == ISC_R_NOTIMPLEMENTED) {
2141 result = ISC_R_SUCCESS;
2142 }
2143 if (result != ISC_R_SUCCESS) {
2144 goto cleanup;
2145 }
2146 }
2147
2148 if (!dns_db_ispersistent(db)) {
2149 if (zone->masterfile != NULL) {
2150 result = zone_startload(db, zone, loadtime);
2151 } else {
2152 result = DNS_R_NOMASTERFILE;
2153 if (zone->type == dns_zone_master ||
2154 (zone->type == dns_zone_redirect &&
2155 zone->masters == NULL)) {
2156 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2157 ISC_LOG_ERROR,
2158 "loading zone: "
2159 "no master file configured");
2160 goto cleanup;
2161 }
2162 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2163 ISC_LOG_INFO, "loading zone: "
2164 "no master file configured: continuing");
2165 }
2166 }
2167
2168 if (result == DNS_R_CONTINUE) {
2169 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2170 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
2171 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2172 goto cleanup;
2173 }
2174
2175 result = zone_postload(zone, db, loadtime, result);
2176
2177 cleanup:
2178 if (hasraw)
2179 UNLOCK_ZONE(zone->raw);
2180 if (!locked)
2181 UNLOCK_ZONE(zone);
2182 if (db != NULL)
2183 dns_db_detach(&db);
2184 return (result);
2185}
2186
2187isc_result_t
2188dns_zone_load(dns_zone_t *zone, bool newonly) {
2189 return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2190}
2191
2192static void
2193zone_asyncload(isc_task_t *task, isc_event_t *event) {
2194 dns_asyncload_t *asl = event->ev_arg;
2195 dns_zone_t *zone = asl->zone;
2196 isc_result_t result;
2197
2198 UNUSED(task);
2199
2200 REQUIRE(DNS_ZONE_VALID(zone));
2201
2202 isc_event_free(&event);
2203
2204 LOCK_ZONE(zone);
2205 result = zone_load(zone, asl->flags, true);
2206 if (result != DNS_R_CONTINUE) {
2207 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2208 }
2209 UNLOCK_ZONE(zone);
2210
2211 /* Inform the zone table we've finished loading */
2212 if (asl->loaded != NULL)
2213 (asl->loaded)(asl->loaded_arg, zone, task);
2214
2215 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2216 dns_zone_idetach(&zone);
2217}
2218
2219isc_result_t
2220dns_zone_asyncload(dns_zone_t *zone, bool newonly,
2221 dns_zt_zoneloaded_t done, void *arg)
2222{
2223 isc_event_t *e;
2224 dns_asyncload_t *asl = NULL;
2225 isc_result_t result = ISC_R_SUCCESS;
2226
2227 REQUIRE(DNS_ZONE_VALID(zone));
2228
2229 if (zone->zmgr == NULL)
2230 return (ISC_R_FAILURE);
2231
2232 /* If we already have a load pending, stop now */
2233 LOCK_ZONE(zone);
2234 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2235 UNLOCK_ZONE(zone);
2236 return (ISC_R_ALREADYRUNNING);
2237 }
2238
2239 asl = isc_mem_get(zone->mctx, sizeof (*asl));
2240 if (asl == NULL)
2241 CHECK(ISC_R_NOMEMORY);
2242
2243 asl->zone = NULL;
2244 asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2245 asl->loaded = done;
2246 asl->loaded_arg = arg;
2247
2248 e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
2249 DNS_EVENT_ZONELOAD,
2250 zone_asyncload, asl,
2251 sizeof(isc_event_t));
2252 if (e == NULL)
2253 CHECK(ISC_R_NOMEMORY);
2254
2255 zone_iattach(zone, &asl->zone);
2256 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2257 isc_task_send(zone->loadtask, &e);
2258 UNLOCK_ZONE(zone);
2259
2260 return (ISC_R_SUCCESS);
2261
2262 failure:
2263 if (asl != NULL)
2264 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2265 UNLOCK_ZONE(zone);
2266 return (result);
2267}
2268
2269bool
2270dns__zone_loadpending(dns_zone_t *zone) {
2271 REQUIRE(DNS_ZONE_VALID(zone));
2272
2273 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2274}
2275
2276isc_result_t
2277dns_zone_loadandthaw(dns_zone_t *zone) {
2278 isc_result_t result;
2279
2280 if (inline_raw(zone))
2281 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
2282 false);
2283 else
2284 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2285
2286 switch (result) {
2287 case DNS_R_CONTINUE:
2288 /* Deferred thaw. */
2289 break;
2290 case DNS_R_UPTODATE:
2291 case ISC_R_SUCCESS:
2292 case DNS_R_SEENINCLUDE:
2293 zone->update_disabled = false;
2294 break;
2295 case DNS_R_NOMASTERFILE:
2296 zone->update_disabled = false;
2297 break;
2298 default:
2299 /* Error, remain in disabled state. */
2300 break;
2301 }
2302 return (result);
2303}
2304
2305static unsigned int
2306get_master_options(dns_zone_t *zone) {
2307 unsigned int options;
2308
2309 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2310 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2311 (zone->type == dns_zone_redirect && zone->masters == NULL))
2312 {
2313 options |= DNS_MASTER_SLAVE;
2314 }
2315 if (zone->type == dns_zone_key) {
2316 options |= DNS_MASTER_KEY;
2317 }
2318 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2319 options |= DNS_MASTER_CHECKNS;
2320 }
2321 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2322 options |= DNS_MASTER_FATALNS;
2323 }
2324 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2325 options |= DNS_MASTER_CHECKNAMES;
2326 }
2327 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2328 options |= DNS_MASTER_CHECKNAMESFAIL;
2329 }
2330 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2331 options |= DNS_MASTER_CHECKMX;
2332 }
2333 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2334 options |= DNS_MASTER_CHECKMXFAIL;
2335 }
2336 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2337 options |= DNS_MASTER_CHECKWILDCARD;
2338 }
2339 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2340 options |= DNS_MASTER_CHECKTTL;
2341 }
2342
2343 return (options);
2344}
2345
2346static void
2347zone_registerinclude(const char *filename, void *arg) {
2348 isc_result_t result;
2349 dns_zone_t *zone = (dns_zone_t *) arg;
2350 dns_include_t *inc = NULL;
2351
2352 REQUIRE(DNS_ZONE_VALID(zone));
2353
2354 if (filename == NULL)
2355 return;
2356
2357 /*
2358 * Suppress duplicates.
2359 */
2360 for (inc = ISC_LIST_HEAD(zone->newincludes);
2361 inc != NULL;
2362 inc = ISC_LIST_NEXT(inc, link))
2363 if (strcmp(filename, inc->name) == 0)
2364 return;
2365
2366 inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2367 if (inc == NULL)
2368 return;
2369 inc->name = isc_mem_strdup(zone->mctx, filename);
2370 if (inc->name == NULL) {
2371 isc_mem_put(zone->mctx, inc, sizeof(dns_include_t));
2372 return;
2373 }
2374 ISC_LINK_INIT(inc, link);
2375
2376 result = isc_file_getmodtime(filename, &inc->filetime);
2377 if (result != ISC_R_SUCCESS)
2378 isc_time_settoepoch(&inc->filetime);
2379
2380 ISC_LIST_APPEND(zone->newincludes, inc, link);
2381}
2382
2383static void
2384zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2385 dns_load_t *load = event->ev_arg;
2386 isc_result_t result = ISC_R_SUCCESS;
2387 unsigned int options;
2388
2389 REQUIRE(DNS_LOAD_VALID(load));
2390
2391 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2392 result = ISC_R_CANCELED;
2393 isc_event_free(&event);
2394 if (result == ISC_R_CANCELED)
2395 goto fail;
2396
2397 options = get_master_options(load->zone);
2398
2399 result = dns_master_loadfileinc(load->zone->masterfile,
2400 dns_db_origin(load->db),
2401 dns_db_origin(load->db),
2402 load->zone->rdclass, options, 0,
2403 &load->callbacks, task,
2404 zone_loaddone, load,
2405 &load->zone->lctx,
2406 zone_registerinclude,
2407 load->zone, load->zone->mctx,
2408 load->zone->masterformat,
2409 load->zone->maxttl);
2410 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2411 result != DNS_R_SEENINCLUDE)
2412 goto fail;
2413 return;
2414
2415 fail:
2416 zone_loaddone(load, result);
2417}
2418
2419static void
2420get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2421 isc_result_t result;
2422 unsigned int soacount;
2423
2424 LOCK(&raw->lock);
2425 if (raw->db != NULL) {
2426 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
2427 &rawdata->sourceserial,
2428 NULL, NULL, NULL, NULL,
2429 NULL);
2430 if (result == ISC_R_SUCCESS && soacount > 0U)
2431 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2432 }
2433 UNLOCK(&raw->lock);
2434}
2435
2436static void
2437zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2438 const char me[] = "zone_gotwritehandle";
2439 dns_zone_t *zone = event->ev_arg;
2440 isc_result_t result = ISC_R_SUCCESS;
2441 dns_dbversion_t *version = NULL;
2442 dns_masterrawheader_t rawdata;
2443
2444 REQUIRE(DNS_ZONE_VALID(zone));
2445 INSIST(task == zone->task);
2446 ENTER;
2447
2448 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2449 result = ISC_R_CANCELED;
2450 isc_event_free(&event);
2451 if (result == ISC_R_CANCELED)
2452 goto fail;
2453
2454 LOCK_ZONE(zone);
2455 INSIST(zone != zone->raw);
2456 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2457 if (zone->db != NULL) {
2458 const dns_master_style_t *output_style;
2459
2460 dns_db_currentversion(zone->db, &version);
2461 dns_master_initrawheader(&rawdata);
2462 if (inline_secure(zone))
2463 get_raw_serial(zone->raw, &rawdata);
2464 if (zone->type == dns_zone_key)
2465 output_style = &dns_master_style_keyzone;
2466 else if (zone->masterstyle != NULL)
2467 output_style = zone->masterstyle;
2468 else
2469 output_style = &dns_master_style_default;
2470 result = dns_master_dumpinc(zone->mctx, zone->db, version,
2471 output_style, zone->masterfile,
2472 zone->task, dump_done, zone,
2473 &zone->dctx, zone->masterformat,
2474 &rawdata);
2475 dns_db_closeversion(zone->db, &version, false);
2476 } else
2477 result = ISC_R_CANCELED;
2478 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2479 UNLOCK_ZONE(zone);
2480 if (result != DNS_R_CONTINUE)
2481 goto fail;
2482 return;
2483
2484 fail:
2485 dump_done(zone, result);
2486}
2487
2488/*
2489 * Save the raw serial number for inline-signing zones.
2490 * (XXX: Other information from the header will be used
2491 * for other purposes in the future, but for now this is
2492 * all we're interested in.)
2493 */
2494static void
2495zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2496 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
2497 return;
2498
2499 zone->sourceserial = header->sourceserial;
2500 zone->sourceserialset = true;
2501}
2502
2503void
2504dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2505 if (zone == NULL)
2506 return;
2507
2508 LOCK_ZONE(zone);
2509 zone_setrawdata(zone, header);
2510 UNLOCK_ZONE(zone);
2511}
2512
2513static isc_result_t
2514zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2515 const char me[] = "zone_startload";
2516 dns_load_t *load;
2517 isc_result_t result;
2518 isc_result_t tresult;
2519 unsigned int options;
2520
2521 ENTER;
2522
2523 dns_zone_rpz_enable_db(zone, db);
2524 dns_zone_catz_enable_db(zone, db);
2525
2526 options = get_master_options(zone);
2527 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2528 options |= DNS_MASTER_MANYERRORS;
2529 }
2530
2531 if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2532 load = isc_mem_get(zone->mctx, sizeof(*load));
2533 if (load == NULL)
2534 return (ISC_R_NOMEMORY);
2535
2536 load->mctx = NULL;
2537 load->zone = NULL;
2538 load->db = NULL;
2539 load->loadtime = loadtime;
2540 load->magic = LOAD_MAGIC;
2541
2542 isc_mem_attach(zone->mctx, &load->mctx);
2543 zone_iattach(zone, &load->zone);
2544 dns_db_attach(db, &load->db);
2545 dns_rdatacallbacks_init(&load->callbacks);
2546 load->callbacks.rawdata = zone_setrawdata;
2547 zone_iattach(zone, &load->callbacks.zone);
2548 result = dns_db_beginload(db, &load->callbacks);
2549 if (result != ISC_R_SUCCESS) {
2550 goto cleanup;
2551 }
2552 result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2553 zone_gotreadhandle, load,
2554 &zone->readio);
2555 if (result != ISC_R_SUCCESS) {
2556 /*
2557 * We can't report multiple errors so ignore
2558 * the result of dns_db_endload().
2559 */
2560 (void)dns_db_endload(load->db, &load->callbacks);
2561 goto cleanup;
2562 } else {
2563 result = DNS_R_CONTINUE;
2564 }
2565 } else {
2566 dns_rdatacallbacks_t callbacks;
2567
2568 dns_rdatacallbacks_init(&callbacks);
2569 callbacks.rawdata = zone_setrawdata;
2570 zone_iattach(zone, &callbacks.zone);
2571 result = dns_db_beginload(db, &callbacks);
2572 if (result != ISC_R_SUCCESS) {
2573 zone_idetach(&callbacks.zone);
2574 return (result);
2575 }
2576 result = dns_master_loadfile(zone->masterfile,
2577 &zone->origin, &zone->origin,
2578 zone->rdclass, options, 0,
2579 &callbacks,
2580 zone_registerinclude,
2581 zone, zone->mctx,
2582 zone->masterformat,
2583 zone->maxttl);
2584 tresult = dns_db_endload(db, &callbacks);
2585 if (result == ISC_R_SUCCESS) {
2586 result = tresult;
2587 }
2588 zone_idetach(&callbacks.zone);
2589 }
2590
2591 return (result);
2592
2593 cleanup:
2594 load->magic = 0;
2595 dns_db_detach(&load->db);
2596 zone_idetach(&load->zone);
2597 zone_idetach(&load->callbacks.zone);
2598 isc_mem_detach(&load->mctx);
2599 isc_mem_put(zone->mctx, load, sizeof(*load));
2600 return (result);
2601}
2602
2603static bool
2604zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2605 dns_name_t *owner)
2606{
2607 isc_result_t result;
2608 char ownerbuf[DNS_NAME_FORMATSIZE];
2609 char namebuf[DNS_NAME_FORMATSIZE];
2610 char altbuf[DNS_NAME_FORMATSIZE];
2611 dns_fixedname_t fixed;
2612 dns_name_t *foundname;
2613 int level;
2614
2615 /*
2616 * "." means the services does not exist.
2617 */
2618 if (dns_name_equal(name, dns_rootname))
2619 return (true);
2620
2621 /*
2622 * Outside of zone.
2623 */
2624 if (!dns_name_issubdomain(name, &zone->origin)) {
2625 if (zone->checkmx != NULL)
2626 return ((zone->checkmx)(zone, name, owner));
2627 return (true);
2628 }
2629
2630 if (zone->type == dns_zone_master)
2631 level = ISC_LOG_ERROR;
2632 else
2633 level = ISC_LOG_WARNING;
2634
2635 foundname = dns_fixedname_initname(&fixed);
2636
2637 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2638 0, 0, NULL, foundname, NULL, NULL);
2639 if (result == ISC_R_SUCCESS)
2640 return (true);
2641
2642 if (result == DNS_R_NXRRSET) {
2643 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2644 0, 0, NULL, foundname, NULL, NULL);
2645 if (result == ISC_R_SUCCESS)
2646 return (true);
2647 }
2648
2649 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2650 dns_name_format(name, namebuf, sizeof namebuf);
2651 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2652 result == DNS_R_EMPTYNAME) {
2653 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2654 level = ISC_LOG_WARNING;
2655 dns_zone_log(zone, level,
2656 "%s/MX '%s' has no address records (A or AAAA)",
2657 ownerbuf, namebuf);
2658 return ((level == ISC_LOG_WARNING) ? true : false);
2659 }
2660
2661 if (result == DNS_R_CNAME) {
2662 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2663 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2664 level = ISC_LOG_WARNING;
2665 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2666 dns_zone_log(zone, level,
2667 "%s/MX '%s' is a CNAME (illegal)",
2668 ownerbuf, namebuf);
2669 return ((level == ISC_LOG_WARNING) ? true : false);
2670 }
2671
2672 if (result == DNS_R_DNAME) {
2673 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2674 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2675 level = ISC_LOG_WARNING;
2676 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2677 dns_name_format(foundname, altbuf, sizeof altbuf);
2678 dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2679 " '%s' (illegal)", ownerbuf, namebuf,
2680 altbuf);
2681 }
2682 return ((level == ISC_LOG_WARNING) ? true : false);
2683 }
2684
2685 if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2686 return ((zone->checkmx)(zone, name, owner));
2687
2688 return (true);
2689}
2690
2691static bool
2692zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2693 dns_name_t *owner)
2694{
2695 isc_result_t result;
2696 char ownerbuf[DNS_NAME_FORMATSIZE];
2697 char namebuf[DNS_NAME_FORMATSIZE];
2698 char altbuf[DNS_NAME_FORMATSIZE];
2699 dns_fixedname_t fixed;
2700 dns_name_t *foundname;
2701 int level;
2702
2703 /*
2704 * "." means the services does not exist.
2705 */
2706 if (dns_name_equal(name, dns_rootname))
2707 return (true);
2708
2709 /*
2710 * Outside of zone.
2711 */
2712 if (!dns_name_issubdomain(name, &zone->origin)) {
2713 if (zone->checksrv != NULL)
2714 return ((zone->checksrv)(zone, name, owner));
2715 return (true);
2716 }
2717
2718 if (zone->type == dns_zone_master)
2719 level = ISC_LOG_ERROR;
2720 else
2721 level = ISC_LOG_WARNING;
2722
2723 foundname = dns_fixedname_initname(&fixed);
2724
2725 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2726 0, 0, NULL, foundname, NULL, NULL);
2727 if (result == ISC_R_SUCCESS)
2728 return (true);
2729
2730 if (result == DNS_R_NXRRSET) {
2731 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2732 0, 0, NULL, foundname, NULL, NULL);
2733 if (result == ISC_R_SUCCESS)
2734 return (true);
2735 }
2736
2737 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2738 dns_name_format(name, namebuf, sizeof namebuf);
2739 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2740 result == DNS_R_EMPTYNAME) {
2741 dns_zone_log(zone, level,
2742 "%s/SRV '%s' has no address records (A or AAAA)",
2743 ownerbuf, namebuf);
2744 /* XXX950 make fatal for 9.5.0. */
2745 return (true);
2746 }
2747
2748 if (result == DNS_R_CNAME) {
2749 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2750 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2751 level = ISC_LOG_WARNING;
2752 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2753 dns_zone_log(zone, level,
2754 "%s/SRV '%s' is a CNAME (illegal)",
2755 ownerbuf, namebuf);
2756 return ((level == ISC_LOG_WARNING) ? true : false);
2757 }
2758
2759 if (result == DNS_R_DNAME) {
2760 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2761 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2762 level = ISC_LOG_WARNING;
2763 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2764 dns_name_format(foundname, altbuf, sizeof altbuf);
2765 dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2766 "DNAME '%s' (illegal)", ownerbuf, namebuf,
2767 altbuf);
2768 }
2769 return ((level == ISC_LOG_WARNING) ? true : false);
2770 }
2771
2772 if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2773 return ((zone->checksrv)(zone, name, owner));
2774
2775 return (true);
2776}
2777
2778static bool
2779zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2780 dns_name_t *owner)
2781{
2782 bool answer = true;
2783 isc_result_t result, tresult;
2784 char ownerbuf[DNS_NAME_FORMATSIZE];
2785 char namebuf[DNS_NAME_FORMATSIZE];
2786 char altbuf[DNS_NAME_FORMATSIZE];
2787 dns_fixedname_t fixed;
2788 dns_name_t *foundname;
2789 dns_rdataset_t a;
2790 dns_rdataset_t aaaa;
2791 int level;
2792
2793 /*
2794 * Outside of zone.
2795 */
2796 if (!dns_name_issubdomain(name, &zone->origin)) {
2797 if (zone->checkns != NULL)
2798 return ((zone->checkns)(zone, name, owner, NULL, NULL));
2799 return (true);
2800 }
2801
2802 if (zone->type == dns_zone_master)
2803 level = ISC_LOG_ERROR;
2804 else
2805 level = ISC_LOG_WARNING;
2806
2807 foundname = dns_fixedname_initname(&fixed);
2808 dns_rdataset_init(&a);
2809 dns_rdataset_init(&aaaa);
2810
2811 /*
2812 * Perform a regular lookup to catch DNAME records then look
2813 * for glue.
2814 */
2815 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2816 0, 0, NULL, foundname, &a, NULL);
2817 switch (result) {
2818 case ISC_R_SUCCESS:
2819 case DNS_R_DNAME:
2820 case DNS_R_CNAME:
2821 break;
2822 default:
2823 if (dns_rdataset_isassociated(&a))
2824 dns_rdataset_disassociate(&a);
2825 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2826 DNS_DBFIND_GLUEOK, 0, NULL,
2827 foundname, &a, NULL);
2828 }
2829 if (result == ISC_R_SUCCESS) {
2830 dns_rdataset_disassociate(&a);
2831 return (true);
2832 } else if (result == DNS_R_DELEGATION)
2833 dns_rdataset_disassociate(&a);
2834
2835 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2836 result == DNS_R_GLUE) {
2837 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2838 DNS_DBFIND_GLUEOK, 0, NULL,
2839 foundname, &aaaa, NULL);
2840 if (tresult == ISC_R_SUCCESS) {
2841 if (dns_rdataset_isassociated(&a))
2842 dns_rdataset_disassociate(&a);
2843 dns_rdataset_disassociate(&aaaa);
2844 return (true);
2845 }
2846 if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME)
2847 dns_rdataset_disassociate(&aaaa);
2848 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2849 /*
2850 * Check glue against child zone.
2851 */
2852 if (zone->checkns != NULL)
2853 answer = (zone->checkns)(zone, name, owner,
2854 &a, &aaaa);
2855 if (dns_rdataset_isassociated(&a))
2856 dns_rdataset_disassociate(&a);
2857 if (dns_rdataset_isassociated(&aaaa))
2858 dns_rdataset_disassociate(&aaaa);
2859 return (answer);
2860 }
2861 }
2862
2863 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2864 dns_name_format(name, namebuf, sizeof namebuf);
2865 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2866 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2867 const char *what;
2868 bool required = false;
2869 if (dns_name_issubdomain(name, owner)) {
2870 what = "REQUIRED GLUE ";
2871 required = true;
2872 } else if (result == DNS_R_DELEGATION)
2873 what = "SIBLING GLUE ";
2874 else
2875 what = "";
2876
2877 if (result != DNS_R_DELEGATION || required ||
2878 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2879 dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2880 "address records (A or AAAA)",
2881 ownerbuf, namebuf, what);
2882 /*
2883 * Log missing address record.
2884 */
2885 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2886 (void)(zone->checkns)(zone, name, owner,
2887 &a, &aaaa);
2888 /* XXX950 make fatal for 9.5.0. */
2889 /* answer = false; */
2890 }
2891 } else if (result == DNS_R_CNAME) {
2892 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2893 ownerbuf, namebuf);
2894 /* XXX950 make fatal for 9.5.0. */
2895 /* answer = false; */
2896 } else if (result == DNS_R_DNAME) {
2897 dns_name_format(foundname, altbuf, sizeof altbuf);
2898 dns_zone_log(zone, level,
2899 "%s/NS '%s' is below a DNAME '%s' (illegal)",
2900 ownerbuf, namebuf, altbuf);
2901 /* XXX950 make fatal for 9.5.0. */
2902 /* answer = false; */
2903 }
2904
2905 if (dns_rdataset_isassociated(&a))
2906 dns_rdataset_disassociate(&a);
2907 if (dns_rdataset_isassociated(&aaaa))
2908 dns_rdataset_disassociate(&aaaa);
2909 return (answer);
2910}
2911
2912static bool
2913zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2914 dns_rdataset_t *rdataset)
2915{
2916 dns_rdataset_t tmprdataset;
2917 isc_result_t result;
2918 bool answer = true;
2919 bool format = true;
2920 int level = ISC_LOG_WARNING;
2921 char ownerbuf[DNS_NAME_FORMATSIZE];
2922 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2923 unsigned int count1 = 0;
2924
2925 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2926 level = ISC_LOG_ERROR;
2927
2928 dns_rdataset_init(&tmprdataset);
2929 for (result = dns_rdataset_first(rdataset);
2930 result == ISC_R_SUCCESS;
2931 result = dns_rdataset_next(rdataset)) {
2932 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2933 unsigned int count2 = 0;
2934
2935 count1++;
2936 dns_rdataset_current(rdataset, &rdata1);
2937 dns_rdataset_clone(rdataset, &tmprdataset);
2938 for (result = dns_rdataset_first(&tmprdataset);
2939 result == ISC_R_SUCCESS;
2940 result = dns_rdataset_next(&tmprdataset)) {
2941 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2942 count2++;
2943 if (count1 >= count2)
2944 continue;
2945 dns_rdataset_current(&tmprdataset, &rdata2);
2946 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2947 if (format) {
2948 dns_name_format(owner, ownerbuf,
2949 sizeof ownerbuf);
2950 dns_rdatatype_format(rdata1.type,
2951 typebuf,
2952 sizeof(typebuf));
2953 format = false;
2954 }
2955 dns_zone_log(zone, level, "%s/%s has "
2956 "semantically identical records",
2957 ownerbuf, typebuf);
2958 if (level == ISC_LOG_ERROR)
2959 answer = false;
2960 break;
2961 }
2962 }
2963 dns_rdataset_disassociate(&tmprdataset);
2964 if (!format)
2965 break;
2966 }
2967 return (answer);
2968}
2969
2970static bool
2971zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2972 dns_dbiterator_t *dbiterator = NULL;
2973 dns_dbnode_t *node = NULL;
2974 dns_fixedname_t fixed;
2975 dns_name_t *name;
2976 dns_rdataset_t rdataset;
2977 dns_rdatasetiter_t *rdsit = NULL;
2978 bool ok = true;
2979 isc_result_t result;
2980
2981 name = dns_fixedname_initname(&fixed);
2982 dns_rdataset_init(&rdataset);
2983
2984 result = dns_db_createiterator(db, 0, &dbiterator);
2985 if (result != ISC_R_SUCCESS)
2986 return (true);
2987
2988 for (result = dns_dbiterator_first(dbiterator);
2989 result == ISC_R_SUCCESS;
2990 result = dns_dbiterator_next(dbiterator)) {
2991 result = dns_dbiterator_current(dbiterator, &node, name);
2992 if (result != ISC_R_SUCCESS)
2993 continue;
2994
2995 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2996 if (result != ISC_R_SUCCESS)
2997 continue;
2998
2999 for (result = dns_rdatasetiter_first(rdsit);
3000 result == ISC_R_SUCCESS;
3001 result = dns_rdatasetiter_next(rdsit)) {
3002 dns_rdatasetiter_current(rdsit, &rdataset);
3003 if (!zone_rrset_check_dup(zone, name, &rdataset))
3004 ok = false;
3005 dns_rdataset_disassociate(&rdataset);
3006 }
3007 dns_rdatasetiter_destroy(&rdsit);
3008 dns_db_detachnode(db, &node);
3009 }
3010
3011 if (node != NULL)
3012 dns_db_detachnode(db, &node);
3013 dns_dbiterator_destroy(&dbiterator);
3014
3015 return (ok);
3016}
3017
3018static bool
3019isspf(const dns_rdata_t *rdata) {
3020 char buf[1024];
3021 const unsigned char *data = rdata->data;
3022 unsigned int rdl = rdata->length, i = 0, tl, len;
3023
3024 while (rdl > 0U) {
3025 len = tl = *data;
3026 ++data;
3027 --rdl;
3028 INSIST(tl <= rdl);
3029 if (len > sizeof(buf) - i - 1)
3030 len = sizeof(buf) - i - 1;
3031 memmove(buf + i, data, len);
3032 i += len;
3033 data += tl;
3034 rdl -= tl;
3035 }
3036
3037 if (i < 6U)
3038 return(false);
3039
3040 buf[i] = 0;
3041 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
3042 return (true);
3043 return (false);
3044}
3045
3046static bool
3047integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3048 dns_dbiterator_t *dbiterator = NULL;
3049 dns_dbnode_t *node = NULL;
3050 dns_rdataset_t rdataset;
3051 dns_fixedname_t fixed;
3052 dns_fixedname_t fixedbottom;
3053 dns_rdata_mx_t mx;
3054 dns_rdata_ns_t ns;
3055 dns_rdata_in_srv_t srv;
3056 dns_rdata_t rdata;
3057 dns_name_t *name;
3058 dns_name_t *bottom;
3059 isc_result_t result;
3060 bool ok = true, have_spf, have_txt;
3061
3062 name = dns_fixedname_initname(&fixed);
3063 bottom = dns_fixedname_initname(&fixedbottom);
3064 dns_rdataset_init(&rdataset);
3065 dns_rdata_init(&rdata);
3066
3067 result = dns_db_createiterator(db, 0, &dbiterator);
3068 if (result != ISC_R_SUCCESS)
3069 return (true);
3070
3071 result = dns_dbiterator_first(dbiterator);
3072 while (result == ISC_R_SUCCESS) {
3073 result = dns_dbiterator_current(dbiterator, &node, name);
3074 if (result != ISC_R_SUCCESS)
3075 goto cleanup;
3076
3077 /*
3078 * Is this name visible in the zone?
3079 */
3080 if (!dns_name_issubdomain(name, &zone->origin) ||
3081 (dns_name_countlabels(bottom) > 0 &&
3082 dns_name_issubdomain(name, bottom)))
3083 goto next;
3084
3085 /*
3086 * Don't check the NS records at the origin.
3087 */
3088 if (dns_name_equal(name, &zone->origin))
3089 goto checkfordname;
3090
3091 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3092 0, 0, &rdataset, NULL);
3093 if (result != ISC_R_SUCCESS)
3094 goto checkfordname;
3095 /*
3096 * Remember bottom of zone due to NS.
3097 */
3098 dns_name_copy(name, bottom, NULL);
3099
3100 result = dns_rdataset_first(&rdataset);
3101 while (result == ISC_R_SUCCESS) {
3102 dns_rdataset_current(&rdataset, &rdata);
3103 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3104 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3105 if (!zone_check_glue(zone, db, &ns.name, name))
3106 ok = false;
3107 dns_rdata_reset(&rdata);
3108 result = dns_rdataset_next(&rdataset);
3109 }
3110 dns_rdataset_disassociate(&rdataset);
3111 goto next;
3112
3113 checkfordname:
3114 result = dns_db_findrdataset(db, node, NULL,
3115 dns_rdatatype_dname, 0, 0,
3116 &rdataset, NULL);
3117 if (result == ISC_R_SUCCESS) {
3118 /*
3119 * Remember bottom of zone due to DNAME.
3120 */
3121 dns_name_copy(name, bottom, NULL);
3122 dns_rdataset_disassociate(&rdataset);
3123 }
3124
3125 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3126 0, 0, &rdataset, NULL);
3127 if (result != ISC_R_SUCCESS)
3128 goto checksrv;
3129 result = dns_rdataset_first(&rdataset);
3130 while (result == ISC_R_SUCCESS) {
3131 dns_rdataset_current(&rdataset, &rdata);
3132 result = dns_rdata_tostruct(&rdata, &mx, NULL);
3133 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3134 if (!zone_check_mx(zone, db, &mx.mx, name))
3135 ok = false;
3136 dns_rdata_reset(&rdata);
3137 result = dns_rdataset_next(&rdataset);
3138 }
3139 dns_rdataset_disassociate(&rdataset);
3140
3141 checksrv:
3142 if (zone->rdclass != dns_rdataclass_in)
3143 goto next;
3144 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3145 0, 0, &rdataset, NULL);
3146 if (result != ISC_R_SUCCESS)
3147 goto checkspf;
3148 result = dns_rdataset_first(&rdataset);
3149 while (result == ISC_R_SUCCESS) {
3150 dns_rdataset_current(&rdataset, &rdata);
3151 result = dns_rdata_tostruct(&rdata, &srv, NULL);
3152 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3153 if (!zone_check_srv(zone, db, &srv.target, name))
3154 ok = false;
3155 dns_rdata_reset(&rdata);
3156 result = dns_rdataset_next(&rdataset);
3157 }
3158 dns_rdataset_disassociate(&rdataset);
3159
3160 checkspf:
3161 /*
3162 * Check if there is a type SPF record without an
3163 * SPF-formatted type TXT record also being present.
3164 */
3165 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
3166 goto next;
3167 if (zone->rdclass != dns_rdataclass_in)
3168 goto next;
3169 have_spf = have_txt = false;
3170 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3171 0, 0, &rdataset, NULL);
3172 if (result == ISC_R_SUCCESS) {
3173 dns_rdataset_disassociate(&rdataset);
3174 have_spf = true;
3175 }
3176 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3177 0, 0, &rdataset, NULL);
3178 if (result != ISC_R_SUCCESS)
3179 goto notxt;
3180 result = dns_rdataset_first(&rdataset);
3181 while (result == ISC_R_SUCCESS) {
3182 dns_rdataset_current(&rdataset, &rdata);
3183 have_txt = isspf(&rdata);
3184 dns_rdata_reset(&rdata);
3185 if (have_txt)
3186 break;
3187 result = dns_rdataset_next(&rdataset);
3188 }
3189 dns_rdataset_disassociate(&rdataset);
3190
3191 notxt:
3192 if (have_spf && !have_txt) {
3193 char namebuf[DNS_NAME_FORMATSIZE];
3194
3195 dns_name_format(name, namebuf, sizeof(namebuf));
3196 dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
3197 "SPF record but no SPF TXT record found, "
3198 "add matching type TXT record", namebuf);
3199 }
3200
3201 next:
3202 dns_db_detachnode(db, &node);
3203 result = dns_dbiterator_next(dbiterator);
3204 }
3205
3206 cleanup:
3207 if (node != NULL)
3208 dns_db_detachnode(db, &node);
3209 dns_dbiterator_destroy(&dbiterator);
3210
3211 return (ok);
3212}
3213
3214/*
3215 * OpenSSL verification of RSA keys with exponent 3 is known to be
3216 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
3217 * if they are in use.
3218 */
3219static void
3220zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3221 dns_dbnode_t *node = NULL;
3222 dns_dbversion_t *version = NULL;
3223 dns_rdata_dnskey_t dnskey;
3224 dns_rdata_t rdata = DNS_RDATA_INIT;
3225 dns_rdataset_t rdataset;
3226 isc_result_t result;
3227 bool logit, foundrsa = false;
3228 const char *algorithm;
3229
3230 result = dns_db_findnode(db, &zone->origin, false, &node);
3231 if (result != ISC_R_SUCCESS) {
3232 goto cleanup;
3233 }
3234
3235 dns_db_currentversion(db, &version);
3236 dns_rdataset_init(&rdataset);
3237 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3238 dns_rdatatype_none, 0, &rdataset, NULL);
3239 if (result != ISC_R_SUCCESS) {
3240 goto cleanup;
3241 }
3242
3243 for (result = dns_rdataset_first(&rdataset);
3244 result == ISC_R_SUCCESS;
3245 result = dns_rdataset_next(&rdataset))
3246 {
3247 dns_rdataset_current(&rdataset, &rdata);
3248 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3249 INSIST(result == ISC_R_SUCCESS);
3250
3251 /* RFC 3110, section 4: Performance Considerations:
3252 *
3253 * A public exponent of 3 minimizes the effort needed to verify
3254 * a signature. Use of 3 as the public exponent is weak for
3255 * confidentiality uses since, if the same data can be collected
3256 * encrypted under three different keys with an exponent of 3
3257 * then, using the Chinese Remainder Theorem [NETSEC], the
3258 * original plain text can be easily recovered. If a key is
3259 * known to be used only for authentication, as is the case with
3260 * DNSSEC, then an exponent of 3 is acceptable. However other
3261 * applications in the future may wish to leverage DNS
3262 * distributed keys for applications that do require
3263 * confidentiality. For keys which might have such other uses,
3264 * a more conservative choice would be 65537 (F4, the fourth
3265 * fermat number).
3266 */
3267 if (dnskey.algorithm == DST_ALG_RSASHA1 &&
3268 dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3269 dnskey.data[1] == 3)
3270 {
3271 if (dnskey.algorithm == DST_ALG_RSASHA1) {
3272 logit = !foundrsa;
3273 foundrsa = true;
3274 algorithm = "RSASHA1";
3275 }
3276 if (logit) {
3277 dnssec_log(zone, ISC_LOG_WARNING,
3278 "weak %s (%u) key found "
3279 "(exponent=3)", algorithm,
3280 dnskey.algorithm);
3281 }
3282 }
3283 dns_rdata_reset(&rdata);
3284 }
3285 dns_rdataset_disassociate(&rdataset);
3286
3287 cleanup:
3288 if (node != NULL) {
3289 dns_db_detachnode(db, &node);
3290 }
3291 if (version != NULL) {
3292 dns_db_closeversion(db, &version, false);
3293 }
3294}
3295
3296static void
3297resume_signingwithkey(dns_zone_t *zone) {
3298 dns_dbnode_t *node = NULL;
3299 dns_dbversion_t *version = NULL;
3300 dns_rdata_t rdata = DNS_RDATA_INIT;
3301 dns_rdataset_t rdataset;
3302 isc_result_t result;
3303 dns_db_t *db = NULL;
3304
3305 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3306 if (zone->db != NULL) {
3307 dns_db_attach(zone->db, &db);
3308 }
3309 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3310 if (db == NULL) {
3311 goto cleanup;
3312 }
3313
3314 result = dns_db_findnode(db, &zone->origin, false, &node);
3315 if (result != ISC_R_SUCCESS) {
3316 goto cleanup;
3317 }
3318
3319 dns_db_currentversion(db, &version);
3320 dns_rdataset_init(&rdataset);
3321 result = dns_db_findrdataset(db, node, version,
3322 zone->privatetype,
3323 dns_rdatatype_none, 0,
3324 &rdataset, NULL);
3325 if (result != ISC_R_SUCCESS) {
3326 INSIST(!dns_rdataset_isassociated(&rdataset));
3327 goto cleanup;
3328 }
3329
3330 for (result = dns_rdataset_first(&rdataset);
3331 result == ISC_R_SUCCESS;
3332 result = dns_rdataset_next(&rdataset))
3333 {
3334 dns_rdataset_current(&rdataset, &rdata);
3335 if (rdata.length != 5 ||
3336 rdata.data[0] == 0 || rdata.data[4] != 0)
3337 {
3338 dns_rdata_reset(&rdata);
3339 continue;
3340 }
3341
3342 result = zone_signwithkey(zone, rdata.data[0],
3343 (rdata.data[1] << 8) | rdata.data[2],
3344 rdata.data[3]);
3345 if (result != ISC_R_SUCCESS) {
3346 dnssec_log(zone, ISC_LOG_ERROR,
3347 "zone_signwithkey failed: %s",
3348 dns_result_totext(result));
3349 }
3350 dns_rdata_reset(&rdata);
3351 }
3352 dns_rdataset_disassociate(&rdataset);
3353
3354 cleanup:
3355 if (db != NULL) {
3356 if (node != NULL) {
3357 dns_db_detachnode(db, &node);
3358 }
3359 if (version != NULL) {
3360 dns_db_closeversion(db, &version, false);
3361 }
3362 dns_db_detach(&db);
3363 }
3364}
3365
3366/*
3367 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3368 * supplied NSEC3PARAM RDATA.
3369 *
3370 * Zone must be locked by caller.
3371 */
3372static isc_result_t
3373zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3374 dns_nsec3chain_t *nsec3chain, *current;
3375 dns_dbversion_t *version = NULL;
3376 bool nseconly = false, nsec3ok = false;
3377 isc_result_t result;
3378 isc_time_t now;
3379 unsigned int options = 0;
3380 char saltbuf[255*2+1];
3381 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3382 dns_db_t *db = NULL;
3383
3384 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3385 if (zone->db != NULL) {
3386 dns_db_attach(zone->db, &db);
3387 }
3388 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3389
3390 if (db == NULL) {
3391 result = ISC_R_SUCCESS;
3392 goto cleanup;
3393 }
3394
3395 /*
3396 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3397 * chain from it is pointless as it would not be possible for the
3398 * latter to exist in the first place.
3399 */
3400 dns_db_currentversion(db, &version);
3401 result = dns_nsec_nseconly(db, version, &nseconly);
3402 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3403 dns_db_closeversion(db, &version, false);
3404 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3405 result = ISC_R_SUCCESS;
3406 goto cleanup;
3407 }
3408
3409 /*
3410 * Allocate and initialize structure preserving state of
3411 * adding/removing records belonging to this NSEC3 chain between
3412 * separate zone_nsec3chain() calls.
3413 */
3414 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3415 if (nsec3chain == NULL) {
3416 result = ISC_R_NOMEMORY;
3417 goto cleanup;
3418 }
3419
3420 nsec3chain->magic = 0;
3421 nsec3chain->done = false;
3422 nsec3chain->db = NULL;
3423 nsec3chain->dbiterator = NULL;
3424 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3425 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3426 nsec3chain->nsec3param.hash = nsec3param->hash;
3427 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3428 nsec3chain->nsec3param.flags = nsec3param->flags;
3429 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3430 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3431 nsec3chain->nsec3param.salt = nsec3chain->salt;
3432 nsec3chain->seen_nsec = false;
3433 nsec3chain->delete_nsec = false;
3434 nsec3chain->save_delete_nsec = false;
3435
3436 /*
3437 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3438 */
3439 if (nsec3param->flags == 0) {
3440 strlcpy(flags, "NONE", sizeof(flags));
3441 } else {
3442 flags[0] = '\0';
3443 if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3444 strlcat(flags, "REMOVE", sizeof(flags));
3445 }
3446 if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3447 if (flags[0] == '\0') {
3448 strlcpy(flags, "INITIAL", sizeof(flags));
3449 } else {
3450 strlcat(flags, "|INITIAL", sizeof(flags));
3451 }
3452 }
3453 if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3454 if (flags[0] == '\0') {
3455 strlcpy(flags, "CREATE", sizeof(flags));
3456 } else {
3457 strlcat(flags, "|CREATE", sizeof(flags));
3458 }
3459 }
3460 if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3461 if (flags[0] == '\0') {
3462 strlcpy(flags, "NONSEC", sizeof(flags));
3463 } else {
3464 strlcat(flags, "|NONSEC", sizeof(flags));
3465 }
3466 }
3467 if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3468 if (flags[0] == '\0') {
3469 strlcpy(flags, "OPTOUT", sizeof(flags));
3470 } else {
3471 strlcat(flags, "|OPTOUT", sizeof(flags));
3472 }
3473 }
3474 }
3475 result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3476 sizeof(saltbuf));
3477 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3478 dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3479 nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3480
3481 /*
3482 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3483 * currently being processed, interrupt its processing to avoid
3484 * simultaneously adding and removing records for the same NSEC3 chain.
3485 */
3486 for (current = ISC_LIST_HEAD(zone->nsec3chain);
3487 current != NULL;
3488 current = ISC_LIST_NEXT(current, link))
3489 {
3490 if ((current->db == db) &&
3491 (current->nsec3param.hash == nsec3param->hash) &&
3492 (current->nsec3param.iterations ==
3493 nsec3param->iterations) &&
3494 (current->nsec3param.salt_length ==
3495 nsec3param->salt_length) &&
3496 memcmp(current->nsec3param.salt, nsec3param->salt,
3497 nsec3param->salt_length) == 0)
3498 {
3499 current->done = true;
3500 }
3501 }
3502
3503 /*
3504 * Attach zone database to the structure initialized above and create
3505 * an iterator for it with appropriate options in order to avoid
3506 * creating NSEC3 records for NSEC3 records.
3507 */
3508 dns_db_attach(db, &nsec3chain->db);
3509 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3510 options = DNS_DB_NONSEC3;
3511 }
3512 result = dns_db_createiterator(nsec3chain->db, options,
3513 &nsec3chain->dbiterator);
3514 if (result == ISC_R_SUCCESS) {
3515 result = dns_dbiterator_first(nsec3chain->dbiterator);
3516 }
3517 if (result == ISC_R_SUCCESS) {
3518 /*
3519 * Database iterator initialization succeeded. We are now
3520 * ready to kick off adding/removing records belonging to this
3521 * NSEC3 chain. Append the structure initialized above to the
3522 * "nsec3chain" list for the zone and set the appropriate zone
3523 * timer so that zone_nsec3chain() is called as soon as
3524 * possible.
3525 */
3526 dns_dbiterator_pause(nsec3chain->dbiterator);
3527 ISC_LIST_INITANDAPPEND(zone->nsec3chain,
3528 nsec3chain, link);
3529 nsec3chain = NULL;
3530 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3531 TIME_NOW(&now);
3532 zone->nsec3chaintime = now;
3533 if (zone->task != NULL) {
3534 zone_settimer(zone, &now);
3535 }
3536 }
3537 }
3538
3539 if (nsec3chain != NULL) {
3540 if (nsec3chain->db != NULL) {
3541 dns_db_detach(&nsec3chain->db);
3542 }
3543 if (nsec3chain->dbiterator != NULL) {
3544 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3545 }
3546 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3547 }
3548
3549 cleanup:
3550 if (db != NULL) {
3551 dns_db_detach(&db);
3552 }
3553 return (result);
3554}
3555
3556/*
3557 * Find private-type records at the zone apex which signal that an NSEC3 chain
3558 * should be added or removed. For each such record, extract NSEC3PARAM RDATA
3559 * and pass it to zone_addnsec3chain().
3560 *
3561 * Zone must be locked by caller.
3562 */
3563static void
3564resume_addnsec3chain(dns_zone_t *zone) {
3565 dns_dbnode_t *node = NULL;
3566 dns_dbversion_t *version = NULL;
3567 dns_rdataset_t rdataset;
3568 isc_result_t result;
3569 dns_rdata_nsec3param_t nsec3param;
3570 bool nseconly = false, nsec3ok = false;
3571 dns_db_t *db = NULL;
3572
3573 INSIST(LOCKED_ZONE(zone));
3574
3575 if (zone->privatetype == 0)
3576 return;
3577
3578 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3579 if (zone->db != NULL) {
3580 dns_db_attach(zone->db, &db);
3581 }
3582 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3583 if (db == NULL) {
3584 goto cleanup;
3585 }
3586
3587 result = dns_db_findnode(db, &zone->origin, false, &node);
3588 if (result != ISC_R_SUCCESS) {
3589 goto cleanup;
3590 }
3591
3592 dns_db_currentversion(db, &version);
3593
3594 /*
3595 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3596 * apex to exist and contain no keys using NSEC-only algorithms.
3597 */
3598 result = dns_nsec_nseconly(db, version, &nseconly);
3599 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3600
3601 /*
3602 * Get the RRset containing all private-type records at the zone apex.
3603 */
3604 dns_rdataset_init(&rdataset);
3605 result = dns_db_findrdataset(db, node, version,
3606 zone->privatetype, dns_rdatatype_none,
3607 0, &rdataset, NULL);
3608 if (result != ISC_R_SUCCESS) {
3609 INSIST(!dns_rdataset_isassociated(&rdataset));
3610 goto cleanup;
3611 }
3612
3613 for (result = dns_rdataset_first(&rdataset);
3614 result == ISC_R_SUCCESS;
3615 result = dns_rdataset_next(&rdataset))
3616 {
3617 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3618 dns_rdata_t rdata = DNS_RDATA_INIT;
3619 dns_rdata_t private = DNS_RDATA_INIT;
3620
3621 dns_rdataset_current(&rdataset, &private);
3622 /*
3623 * Try extracting NSEC3PARAM RDATA from this private-type
3624 * record. Failure means this private-type record does not
3625 * represent an NSEC3PARAM record, so skip it.
3626 */
3627 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3628 sizeof(buf)))
3629 {
3630 continue;
3631 }
3632 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3633 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3634 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3635 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3636 {
3637 /*
3638 * Pass the NSEC3PARAM RDATA contained in this
3639 * private-type record to zone_addnsec3chain() so that
3640 * it can kick off adding or removing NSEC3 records.
3641 */
3642 result = zone_addnsec3chain(zone, &nsec3param);
3643 if (result != ISC_R_SUCCESS) {
3644 dnssec_log(zone, ISC_LOG_ERROR,
3645 "zone_addnsec3chain failed: %s",
3646 dns_result_totext(result));
3647 }
3648 }
3649 }
3650 dns_rdataset_disassociate(&rdataset);
3651
3652 cleanup:
3653 if (db != NULL) {
3654 if (node != NULL) {
3655 dns_db_detachnode(db, &node);
3656 }
3657 if (version != NULL) {
3658 dns_db_closeversion(db, &version, false);
3659 }
3660 dns_db_detach(&db);
3661 }
3662}
3663
3664static void
3665set_resigntime(dns_zone_t *zone) {
3666 dns_rdataset_t rdataset;
3667 dns_fixedname_t fixed;
3668 unsigned int resign;
3669 isc_result_t result;
3670 uint32_t nanosecs;
3671 dns_db_t *db = NULL;
3672
3673 /* We only re-sign zones that can be dynamically updated */
3674 if (zone->update_disabled)
3675 return;
3676
3677 if (!inline_secure(zone) && (zone->type != dns_zone_master ||
3678 (zone->ssutable == NULL &&
3679 (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3680 return;
3681
3682 dns_rdataset_init(&rdataset);
3683 dns_fixedname_init(&fixed);
3684
3685 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3686 if (zone->db != NULL)
3687 dns_db_attach(zone->db, &db);
3688 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3689 if (db == NULL) {
3690 isc_time_settoepoch(&zone->resigntime);
3691 return;
3692 }
3693
3694 result = dns_db_getsigningtime(db, &rdataset,
3695 dns_fixedname_name(&fixed));
3696 if (result != ISC_R_SUCCESS) {
3697 isc_time_settoepoch(&zone->resigntime);
3698 goto cleanup;
3699 }
3700
3701 resign = rdataset.resign - zone->sigresigninginterval;
3702 dns_rdataset_disassociate(&rdataset);
3703 nanosecs = isc_random_uniform(1000000000);
3704 isc_time_set(&zone->resigntime, resign, nanosecs);
3705 cleanup:
3706 dns_db_detach(&db);
3707 return;
3708}
3709
3710static isc_result_t
3711check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3712 dns_dbnode_t *node = NULL;
3713 dns_rdataset_t rdataset;
3714 dns_dbversion_t *version = NULL;
3715 dns_rdata_nsec3param_t nsec3param;
3716 bool ok = false;
3717 isc_result_t result;
3718 dns_rdata_t rdata = DNS_RDATA_INIT;
3719 bool dynamic = (zone->type == dns_zone_master)
3720 ? dns_zone_isdynamic(zone, false) : false;
3721
3722 dns_rdataset_init(&rdataset);
3723 result = dns_db_findnode(db, &zone->origin, false, &node);
3724 if (result != ISC_R_SUCCESS) {
3725 dns_zone_log(zone, ISC_LOG_ERROR,
3726 "nsec3param lookup failure: %s",
3727 dns_result_totext(result));
3728 return (result);
3729 }
3730 dns_db_currentversion(db, &version);
3731
3732 result = dns_db_findrdataset(db, node, version,
3733 dns_rdatatype_nsec3param,
3734 dns_rdatatype_none, 0, &rdataset, NULL);
3735 if (result == ISC_R_NOTFOUND) {
3736 INSIST(!dns_rdataset_isassociated(&rdataset));
3737 result = ISC_R_SUCCESS;
3738 goto cleanup;
3739 }
3740 if (result != ISC_R_SUCCESS) {
3741 INSIST(!dns_rdataset_isassociated(&rdataset));
3742 dns_zone_log(zone, ISC_LOG_ERROR,
3743 "nsec3param lookup failure: %s",
3744 dns_result_totext(result));
3745 goto cleanup;
3746 }
3747
3748 /*
3749 * For dynamic zones we must support every algorithm so we can
3750 * regenerate all the NSEC3 chains.
3751 * For non-dynamic zones we only need to find a supported algorithm.
3752 */
3753 for (result = dns_rdataset_first(&rdataset);
3754 result == ISC_R_SUCCESS;
3755 result = dns_rdataset_next(&rdataset))
3756 {
3757 dns_rdataset_current(&rdataset, &rdata);
3758 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3759 dns_rdata_reset(&rdata);
3760 INSIST(result == ISC_R_SUCCESS);
3761 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3762 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3763 {
3764 dns_zone_log(zone, ISC_LOG_WARNING,
3765 "nsec3 test \"unknown\" hash algorithm found: %u",
3766 nsec3param.hash);
3767 ok = true;
3768 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3769 if (dynamic) {
3770 dns_zone_log(zone, ISC_LOG_ERROR,
3771 "unsupported nsec3 hash algorithm"
3772 " in dynamic zone: %u",
3773 nsec3param.hash);
3774 result = DNS_R_BADZONE;
3775 /* Stop second error message. */
3776 ok = true;
3777 break;
3778 } else
3779 dns_zone_log(zone, ISC_LOG_WARNING,
3780 "unsupported nsec3 hash algorithm: %u",
3781 nsec3param.hash);
3782 } else {
3783 ok = true;
3784 }
3785 }
3786 if (result == ISC_R_NOMORE) {
3787 result = ISC_R_SUCCESS;
3788 }
3789
3790 if (!ok) {
3791 result = DNS_R_BADZONE;
3792 dns_zone_log(zone, ISC_LOG_ERROR,
3793 "no supported nsec3 hash algorithm");
3794 }
3795
3796 cleanup:
3797 if (dns_rdataset_isassociated(&rdataset)) {
3798 dns_rdataset_disassociate(&rdataset);
3799 }
3800 dns_db_closeversion(db, &version, false);
3801 dns_db_detachnode(db, &node);
3802 return (result);
3803}
3804
3805/*
3806 * Set the timer for refreshing the key zone to the soonest future time
3807 * of the set (current timer, keydata->refresh, keydata->addhd,
3808 * keydata->removehd).
3809 */
3810static void
3811set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3812 isc_stdtime_t now, bool force)
3813{
3814 const char me[] = "set_refreshkeytimer";
3815 isc_stdtime_t then;
3816 isc_time_t timenow, timethen;
3817 char timebuf[80];
3818
3819 ENTER;
3820 then = key->refresh;
3821 if (force)
3822 then = now;
3823 if (key->addhd > now && key->addhd < then)
3824 then = key->addhd;
3825 if (key->removehd > now && key->removehd < then)
3826 then = key->removehd;
3827
3828 TIME_NOW(&timenow);
3829 if (then > now)
3830 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3831 else
3832 timethen = timenow;
3833 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3834 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3835 zone->refreshkeytime = timethen;
3836
3837 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3838 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3839 zone_settimer(zone, &timenow);
3840}
3841
3842/*
3843 * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3844 * If the key zone is changed, set '*changed' to true.
3845 */
3846static isc_result_t
3847create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3848 dns_diff_t *diff, dns_keytable_t *keytable,
3849 dns_keynode_t **keynodep, bool *changed)
3850{
3851 const char me[] = "create_keydata";
3852 isc_result_t result = ISC_R_SUCCESS;
3853 isc_buffer_t keyb, dstb;
3854 unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3855 dns_rdata_keydata_t keydata;
3856 dns_rdata_dnskey_t dnskey;
3857 dns_rdata_t rdata = DNS_RDATA_INIT;
3858 dns_keynode_t *keynode;
3859 isc_stdtime_t now;
3860 isc_region_t r;
3861 dst_key_t *key;
3862
3863 REQUIRE(keynodep != NULL);
3864 keynode = *keynodep;
3865
3866 ENTER;
3867 isc_stdtime_get(&now);
3868
3869 /* Loop in case there's more than one key. */
3870 while (result == ISC_R_SUCCESS) {
3871 dns_keynode_t *nextnode = NULL;
3872
3873 key = dns_keynode_key(keynode);
3874 if (key == NULL)
3875 goto skip;
3876
3877 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3878 CHECK(dst_key_todns(key, &dstb));
3879
3880 /* Convert DST key to DNSKEY. */
3881 dns_rdata_reset(&rdata);
3882 isc_buffer_usedregion(&dstb, &r);
3883 dns_rdata_fromregion(&rdata, dst_key_class(key),
3884 dns_rdatatype_dnskey, &r);
3885
3886 /* DSTKEY to KEYDATA. */
3887 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3888 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3889 NULL));
3890
3891 /* KEYDATA to rdata. */
3892 dns_rdata_reset(&rdata);
3893 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3894 CHECK(dns_rdata_fromstruct(&rdata,
3895 zone->rdclass, dns_rdatatype_keydata,
3896 &keydata, &keyb));
3897
3898 /* Add rdata to zone. */
3899 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3900 dst_key_name(key), 0, &rdata));
3901 *changed = true;
3902
3903 /* Refresh new keys from the zone apex as soon as possible. */
3904 set_refreshkeytimer(zone, &keydata, now, true);
3905
3906 skip:
3907 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3908 if (result != ISC_R_NOTFOUND) {
3909 dns_keytable_detachkeynode(keytable, &keynode);
3910 keynode = nextnode;
3911 }
3912 }
3913
3914 if (keynode != NULL)
3915 dns_keytable_detachkeynode(keytable, &keynode);
3916 *keynodep = NULL;
3917
3918 return (ISC_R_SUCCESS);
3919
3920 failure:
3921 return (result);
3922}
3923
3924/*
3925 * Remove from the key zone all the KEYDATA records found in rdataset.
3926 */
3927static isc_result_t
3928delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3929 dns_name_t *name, dns_rdataset_t *rdataset)
3930{
3931 dns_rdata_t rdata = DNS_RDATA_INIT;
3932 isc_result_t result, uresult;
3933
3934 for (result = dns_rdataset_first(rdataset);
3935 result == ISC_R_SUCCESS;
3936 result = dns_rdataset_next(rdataset)) {
3937 dns_rdata_reset(&rdata);
3938 dns_rdataset_current(rdataset, &rdata);
3939 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3940 name, 0, &rdata);
3941 if (uresult != ISC_R_SUCCESS)
3942 return (uresult);
3943 }
3944 if (result == ISC_R_NOMORE)
3945 result = ISC_R_SUCCESS;
3946 return (result);
3947}
3948
3949/*
3950 * Compute the DNSSEC key ID for a DNSKEY record.
3951 */
3952static isc_result_t
3953compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3954 dns_keytag_t *tag)
3955{
3956 isc_result_t result;
3957 dns_rdata_t rdata = DNS_RDATA_INIT;
3958 unsigned char data[4096];
3959 isc_buffer_t buffer;
3960 dst_key_t *dstkey = NULL;
3961
3962 isc_buffer_init(&buffer, data, sizeof(data));
3963 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3964 dns_rdatatype_dnskey, dnskey, &buffer);
3965
3966 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3967 if (result == ISC_R_SUCCESS) {
3968 *tag = dst_key_id(dstkey);
3969 dst_key_free(&dstkey);
3970 }
3971
3972 return (result);
3973}
3974
3975/*
3976 * Add key to the security roots.
3977 */
3978static void
3979trust_key(dns_zone_t *zone, dns_name_t *keyname,
3980 dns_rdata_dnskey_t *dnskey, bool initial,
3981 isc_mem_t *mctx)
3982{
3983 isc_result_t result;
3984 dns_rdata_t rdata = DNS_RDATA_INIT;
3985 unsigned char data[4096];
3986 isc_buffer_t buffer;
3987 dns_keytable_t *sr = NULL;
3988 dst_key_t *dstkey = NULL;
3989
3990 /* Convert dnskey to DST key. */
3991 isc_buffer_init(&buffer, data, sizeof(data));
3992 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3993 dns_rdatatype_dnskey, dnskey, &buffer);
3994
3995 result = dns_view_getsecroots(zone->view, &sr);
3996 if (result != ISC_R_SUCCESS)
3997 goto failure;
3998
3999 CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
4000 CHECK(dns_keytable_add(sr, true, initial, &dstkey));
4001 dns_keytable_detach(&sr);
4002
4003 failure:
4004 if (dstkey != NULL)
4005 dst_key_free(&dstkey);
4006 if (sr != NULL)
4007 dns_keytable_detach(&sr);
4008 return;
4009}
4010
4011/*
4012 * Add a null key to the security roots for so that all queries
4013 * to the zone will fail.
4014 */
4015static void
4016fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4017 isc_result_t result;
4018 dns_keytable_t *sr = NULL;
4019
4020 result = dns_view_getsecroots(zone->view, &sr);
4021 if (result == ISC_R_SUCCESS) {
4022 dns_keytable_marksecure(sr, keyname);
4023 dns_keytable_detach(&sr);
4024 }
4025}
4026
4027/*
4028 * Scan a set of KEYDATA records from the key zone. The ones that are
4029 * valid (i.e., the add holddown timer has expired) become trusted keys.
4030 */
4031static void
4032load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4033 isc_result_t result;
4034 dns_rdata_t rdata = DNS_RDATA_INIT;
4035 dns_rdata_keydata_t keydata;
4036 dns_rdata_dnskey_t dnskey;
4037 isc_mem_t *mctx = zone->mctx;
4038 int trusted = 0, revoked = 0, pending = 0;
4039 isc_stdtime_t now;
4040 dns_keytable_t *sr = NULL;
4041
4042 isc_stdtime_get(&now);
4043
4044 result = dns_view_getsecroots(zone->view, &sr);
4045 if (result == ISC_R_SUCCESS) {
4046 dns_keytable_delete(sr, name);
4047 dns_keytable_detach(&sr);
4048 }
4049
4050 /* Now insert all the accepted trust anchors from this keydata set. */
4051 for (result = dns_rdataset_first(rdataset);
4052 result == ISC_R_SUCCESS;
4053 result = dns_rdataset_next(rdataset))
4054 {
4055 dns_rdata_reset(&rdata);
4056 dns_rdataset_current(rdataset, &rdata);
4057
4058 /* Convert rdata to keydata. */
4059 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4060 if (result == ISC_R_UNEXPECTEDEND) {
4061 continue;
4062 }
4063 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4064
4065 /* Set the key refresh timer to force a fast refresh. */
4066 set_refreshkeytimer(zone, &keydata, now, true);
4067
4068 /* If the removal timer is nonzero, this key was revoked. */
4069 if (keydata.removehd != 0) {
4070 revoked++;
4071 continue;
4072 }
4073
4074 /*
4075 * If the add timer is still pending, this key is not
4076 * trusted yet.
4077 */
4078 if (now < keydata.addhd) {
4079 pending++;
4080 continue;
4081 }
4082
4083 /* Convert keydata to dnskey. */
4084 dns_keydata_todnskey(&keydata, &dnskey, NULL);
4085
4086 /* Add to keytables. */
4087 trusted++;
4088 trust_key(zone, name, &dnskey, (keydata.addhd == 0), mctx);
4089 }
4090
4091 if (trusted == 0 && pending != 0) {
4092 char namebuf[DNS_NAME_FORMATSIZE];
4093 dns_name_format(name, namebuf, sizeof namebuf);
4094 dnssec_log(zone, ISC_LOG_ERROR,
4095 "No valid trust anchors for '%s'!", namebuf);
4096 dnssec_log(zone, ISC_LOG_ERROR,
4097 "%d key(s) revoked, %d still pending",
4098 revoked, pending);
4099 dnssec_log(zone, ISC_LOG_ERROR,
4100 "All queries to '%s' will fail", namebuf);
4101 fail_secure(zone, name);
4102 }
4103}
4104
4105static isc_result_t
4106do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4107 dns_diff_t *diff)
4108{
4109 dns_diff_t temp_diff;
4110 isc_result_t result;
4111
4112 /*
4113 * Create a singleton diff.
4114 */
4115 dns_diff_init(diff->mctx, &temp_diff);
4116 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4117
4118 /*
4119 * Apply it to the database.
4120 */
4121 result = dns_diff_apply(&temp_diff, db, ver);
4122 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4123 if (result != ISC_R_SUCCESS) {
4124 dns_difftuple_free(tuple);
4125 return (result);
4126 }
4127
4128 /*
4129 * Merge it into the current pending journal entry.
4130 */
4131 dns_diff_appendminimal(diff, tuple);
4132
4133 /*
4134 * Do not clear temp_diff.
4135 */
4136 return (ISC_R_SUCCESS);
4137}
4138
4139static isc_result_t
4140update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4141 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4142 dns_rdata_t *rdata)
4143{
4144 dns_difftuple_t *tuple = NULL;
4145 isc_result_t result;
4146 result = dns_difftuple_create(diff->mctx, op,
4147 name, ttl, rdata, &tuple);
4148 if (result != ISC_R_SUCCESS)
4149 return (result);
4150 return (do_one_tuple(&tuple, db, ver, diff));
4151}
4152
4153static isc_result_t
4154update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4155 isc_mem_t *mctx, dns_updatemethod_t method) {
4156 dns_difftuple_t *deltuple = NULL;
4157 dns_difftuple_t *addtuple = NULL;
4158 uint32_t serial;
4159 isc_result_t result;
4160
4161 INSIST(method != dns_updatemethod_none);
4162
4163 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4164 CHECK(dns_difftuple_copy(deltuple, &addtuple));
4165 addtuple->op = DNS_DIFFOP_ADD;
4166
4167 serial = dns_soa_getserial(&addtuple->rdata);
4168 serial = dns_update_soaserial(serial, method);
4169 dns_soa_setserial(serial, &addtuple->rdata);
4170 CHECK(do_one_tuple(&deltuple, db, ver, diff));
4171 CHECK(do_one_tuple(&addtuple, db, ver, diff));
4172 result = ISC_R_SUCCESS;
4173
4174 failure:
4175 if (addtuple != NULL)
4176 dns_difftuple_free(&addtuple);
4177 if (deltuple != NULL)
4178 dns_difftuple_free(&deltuple);
4179 return (result);
4180}
4181
4182/*
4183 * Write all transactions in 'diff' to the zone journal file.
4184 */
4185static isc_result_t
4186zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4187 const char *caller)
4188{
4189 const char me[] = "zone_journal";
4190 const char *journalfile;
4191 isc_result_t result = ISC_R_SUCCESS;
4192 dns_journal_t *journal = NULL;
4193 unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
4194
4195 ENTER;
4196 journalfile = dns_zone_getjournal(zone);
4197 if (journalfile != NULL) {
4198 result = dns_journal_open(zone->mctx, journalfile, mode,
4199 &journal);
4200 if (result != ISC_R_SUCCESS) {
4201 dns_zone_log(zone, ISC_LOG_ERROR,
4202 "%s:dns_journal_open -> %s",
4203 caller, dns_result_totext(result));
4204 return (result);
4205 }
4206
4207 if (sourceserial != NULL)
4208 dns_journal_set_sourceserial(journal, *sourceserial);
4209
4210 result = dns_journal_write_transaction(journal, diff);
4211 if (result != ISC_R_SUCCESS) {
4212 dns_zone_log(zone, ISC_LOG_ERROR,
4213 "%s:dns_journal_write_transaction -> %s",
4214 caller, dns_result_totext(result));
4215 }
4216 dns_journal_destroy(&journal);
4217 }
4218
4219 return (result);
4220}
4221
4222/*
4223 * Create an SOA record for a newly-created zone
4224 */
4225static isc_result_t
4226add_soa(dns_zone_t *zone, dns_db_t *db) {
4227 isc_result_t result;
4228 dns_rdata_t rdata = DNS_RDATA_INIT;
4229 unsigned char buf[DNS_SOA_BUFFERSIZE];
4230 dns_dbversion_t *ver = NULL;
4231 dns_diff_t diff;
4232
4233 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4234
4235 dns_diff_init(zone->mctx, &diff);
4236 result = dns_db_newversion(db, &ver);
4237 if (result != ISC_R_SUCCESS) {
4238 dns_zone_log(zone, ISC_LOG_ERROR,
4239 "add_soa:dns_db_newversion -> %s",
4240 dns_result_totext(result));
4241 goto failure;
4242 }
4243
4244 /* Build SOA record */
4245 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4246 0, 0, 0, 0, 0, buf, &rdata);
4247 if (result != ISC_R_SUCCESS) {
4248 dns_zone_log(zone, ISC_LOG_ERROR,
4249 "add_soa:dns_soa_buildrdata -> %s",
4250 dns_result_totext(result));
4251 goto failure;
4252 }
4253
4254 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
4255 &zone->origin, 0, &rdata);
4256
4257failure:
4258 dns_diff_clear(&diff);
4259 if (ver != NULL)
4260 dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4261
4262 INSIST(ver == NULL);
4263
4264 return (result);
4265}
4266
4267struct addifmissing_arg {
4268 dns_db_t *db;
4269 dns_dbversion_t *ver;
4270 dns_diff_t *diff;
4271 dns_zone_t *zone;
4272 bool *changed;
4273 isc_result_t result;
4274};
4275
4276static void
4277addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
4278 dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4279 dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4280 dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4281 dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4282 bool *changed = ((struct addifmissing_arg *)arg)->changed;
4283 isc_result_t result;
4284 dns_keynode_t *dummy = NULL;
4285
4286 if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS)
4287 return;
4288
4289 if (dns_keynode_managed(keynode)) {
4290 dns_fixedname_t fname;
4291 dns_name_t *keyname;
4292 dst_key_t *key;
4293
4294 key = dns_keynode_key(keynode);
4295 if (key == NULL)
4296 return;
4297 dns_fixedname_init(&fname);
4298
4299 keyname = dst_key_name(key);
4300 result = dns_db_find(db, keyname, ver,
4301 dns_rdatatype_keydata,
4302 DNS_DBFIND_NOWILD, 0, NULL,
4303 dns_fixedname_name(&fname),
4304 NULL, NULL);
4305 if (result == ISC_R_SUCCESS)
4306 return;
4307 dns_keytable_attachkeynode(keytable, keynode, &dummy);
4308 result = create_keydata(zone, db, ver, diff, keytable,
4309 &dummy, changed);
4310 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
4311 ((struct addifmissing_arg *)arg)->result = result;
4312 }
4313};
4314
4315/*
4316 * Synchronize the set of initializing keys found in managed-keys {}
4317 * statements with the set of trust anchors found in the managed-keys.bind
4318 * zone. If a domain is no longer named in managed-keys, delete all keys
4319 * from that domain from the key zone. If a domain is mentioned in in
4320 * managed-keys but there are no references to it in the key zone, load
4321 * the key zone with the initializing key(s) for that domain.
4322 */
4323static isc_result_t
4324sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4325 isc_result_t result = ISC_R_SUCCESS;
4326 bool changed = false;
4327 bool commit = false;
4328 dns_keynode_t *keynode = NULL;
4329 dns_view_t *view = zone->view;
4330 dns_keytable_t *sr = NULL;
4331 dns_dbversion_t *ver = NULL;
4332 dns_diff_t diff;
4333 dns_rriterator_t rrit;
4334 struct addifmissing_arg arg;
4335
4336 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4337
4338 dns_diff_init(zone->mctx, &diff);
4339
4340 CHECK(dns_view_getsecroots(view, &sr));
4341
4342 result = dns_db_newversion(db, &ver);
4343 if (result != ISC_R_SUCCESS) {
4344 dnssec_log(zone, ISC_LOG_ERROR,
4345 "sync_keyzone:dns_db_newversion -> %s",
4346 dns_result_totext(result));
4347 goto failure;
4348 }
4349
4350 /*
4351 * Walk the zone DB. If we find any keys whose names are no longer
4352 * in managed-keys (or *are* in trusted-keys, meaning they are
4353 * permanent and not RFC5011-maintained), delete them from the
4354 * zone. Otherwise call load_secroots(), which loads keys into
4355 * secroots as appropriate.
4356 */
4357 dns_rriterator_init(&rrit, db, ver, 0);
4358 for (result = dns_rriterator_first(&rrit);
4359 result == ISC_R_SUCCESS;
4360 result = dns_rriterator_nextrrset(&rrit))
4361 {
4362 dns_rdataset_t *rdataset = NULL;
4363 dns_name_t *rrname = NULL;
4364 uint32_t ttl;
4365
4366 dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4367 if (!dns_rdataset_isassociated(rdataset)) {
4368 dns_rriterator_destroy(&rrit);
4369 goto failure;
4370 }
4371
4372 if (rdataset->type != dns_rdatatype_keydata) {
4373 continue;
4374 }
4375
4376 result = dns_keytable_find(sr, rrname, &keynode);
4377 if ((result != ISC_R_SUCCESS &&
4378 result != DNS_R_PARTIALMATCH) ||
4379 dns_keynode_managed(keynode) == false)
4380 {
4381 CHECK(delete_keydata(db, ver, &diff,
4382 rrname, rdataset));
4383 changed = true;
4384 } else {
4385 load_secroots(zone, rrname, rdataset);
4386 }
4387
4388 if (keynode != NULL) {
4389 dns_keytable_detachkeynode(sr, &keynode);
4390 }
4391 }
4392 dns_rriterator_destroy(&rrit);
4393
4394 /*
4395 * Now walk secroots to find any managed keys that aren't
4396 * in the zone. If we find any, we add them to the zone.
4397 */
4398 arg.db = db;
4399 arg.ver = ver;
4400 arg.result = ISC_R_SUCCESS;
4401 arg.diff = &diff;
4402 arg.zone = zone;
4403 arg.changed = &changed;
4404 dns_keytable_forall(sr, addifmissing, &arg);
4405 result = arg.result;
4406 if (changed) {
4407 /* Write changes to journal file. */
4408 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
4409 zone->updatemethod));
4410 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4411
4412 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4413 zone_needdump(zone, 30);
4414 commit = true;
4415 }
4416
4417 failure:
4418 if (result != ISC_R_SUCCESS &&
4419 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4420 {
4421 dnssec_log(zone, ISC_LOG_ERROR,
4422 "unable to synchronize managed keys: %s",
4423 dns_result_totext(result));
4424 isc_time_settoepoch(&zone->refreshkeytime);
4425 }
4426 if (keynode != NULL) {
4427 dns_keytable_detachkeynode(sr, &keynode);
4428 }
4429 if (sr != NULL) {
4430 dns_keytable_detach(&sr);
4431 }
4432 if (ver != NULL) {
4433 dns_db_closeversion(db, &ver, commit);
4434 }
4435 dns_diff_clear(&diff);
4436
4437 INSIST(ver == NULL);
4438
4439 return (result);
4440}
4441
4442isc_result_t
4443dns_zone_synckeyzone(dns_zone_t *zone) {
4444 isc_result_t result;
4445 dns_db_t *db = NULL;
4446
4447 if (zone->type != dns_zone_key) {
4448 return (DNS_R_BADZONE);
4449 }
4450
4451 CHECK(dns_zone_getdb(zone, &db));
4452
4453 LOCK_ZONE(zone);
4454 result = sync_keyzone(zone, db);
4455 UNLOCK_ZONE(zone);
4456
4457 failure:
4458 if (db != NULL) {
4459 dns_db_detach(&db);
4460 }
4461 return (result);
4462}
4463
4464static void
4465maybe_send_secure(dns_zone_t *zone) {
4466 isc_result_t result;
4467
4468 /*
4469 * We've finished loading, or else failed to load, an inline-signing
4470 * 'secure' zone. We now need information about the status of the
4471 * 'raw' zone. If we failed to load, then we need it to send a
4472 * copy of its database; if we succeeded, we need it to send its
4473 * serial number so that we can sync with it. If it has not yet
4474 * loaded, we set a flag so that it will send the necessary
4475 * information when it has finished loading.
4476 */
4477 if (zone->raw->db != NULL) {
4478 if (zone->db != NULL) {
4479 uint32_t serial;
4480 unsigned int soacount;
4481
4482 result = zone_get_from_db(zone->raw, zone->raw->db,
4483 NULL, &soacount, &serial,
4484 NULL, NULL, NULL, NULL, NULL);
4485 if (result == ISC_R_SUCCESS && soacount > 0U)
4486 zone_send_secureserial(zone->raw, serial);
4487 } else
4488 zone_send_securedb(zone->raw, zone->raw->db);
4489
4490 } else
4491 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4492}
4493
4494static bool
4495zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4496 isc_result_t result;
4497 bool answer = false;
4498 dns_diff_t diff;
4499
4500 dns_diff_init(mctx, &diff);
4501 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4502 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
4503 answer = true;
4504 dns_diff_clear(&diff);
4505 return (answer);
4506}
4507
4508/*
4509 * The zone is presumed to be locked.
4510 * If this is a inline_raw zone the secure version is also locked.
4511 */
4512static isc_result_t
4513zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4514 isc_result_t result)
4515{
4516 unsigned int soacount = 0;
4517 unsigned int nscount = 0;
4518 unsigned int errors = 0;
4519 uint32_t serial, oldserial, refresh, retry, expire, minimum;
4520 isc_time_t now;
4521 bool needdump = false;
4522 bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4523 bool nomaster = false;
4524 bool had_db = false;
4525 unsigned int options;
4526 dns_include_t *inc;
4527
4528 INSIST(LOCKED_ZONE(zone));
4529 if (inline_raw(zone)) {
4530 INSIST(LOCKED_ZONE(zone->secure));
4531 }
4532
4533 TIME_NOW(&now);
4534
4535 /*
4536 * Initiate zone transfer? We may need a error code that
4537 * indicates that the "permanent" form does not exist.
4538 * XXX better error feedback to log.
4539 */
4540 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4541 if (zone->type == dns_zone_slave ||
4542 zone->type == dns_zone_mirror ||
4543 zone->type == dns_zone_stub ||
4544 (zone->type == dns_zone_redirect &&
4545 zone->masters == NULL))
4546 {
4547 if (result == ISC_R_FILENOTFOUND) {
4548 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4549 ISC_LOG_DEBUG(1),
4550 "no master file");
4551 } else if (result != DNS_R_NOMASTERFILE) {
4552 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4553 ISC_LOG_ERROR,
4554 "loading from master file %s "
4555 "failed: %s",
4556 zone->masterfile,
4557 dns_result_totext(result));
4558 }
4559 } else if (zone->type == dns_zone_master &&
4560 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4561 {
4562 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4563 ISC_LOG_DEBUG(1),
4564 "no master file, requesting db");
4565 maybe_send_secure(zone);
4566 } else {
4567 int level = ISC_LOG_ERROR;
4568 if (zone->type == dns_zone_key &&
4569 result == ISC_R_FILENOTFOUND)
4570 level = ISC_LOG_DEBUG(1);
4571 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4572 "loading from master file %s failed: %s",
4573 zone->masterfile,
4574 dns_result_totext(result));
4575 nomaster = true;
4576 }
4577
4578 if (zone->type != dns_zone_key) {
4579 goto cleanup;
4580 }
4581 }
4582
4583 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4584 "number of nodes in database: %u",
4585 dns_db_nodecount(db));
4586
4587 if (result == DNS_R_SEENINCLUDE) {
4588 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4589 } else {
4590 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4591 }
4592
4593 /*
4594 * If there's no master file for a key zone, then the zone is new:
4595 * create an SOA record. (We do this now, instead of later, so that
4596 * if there happens to be a journal file, we can roll forward from
4597 * a sane starting point.)
4598 */
4599 if (nomaster && zone->type == dns_zone_key) {
4600 result = add_soa(zone, db);
4601 if (result != ISC_R_SUCCESS) {
4602 goto cleanup;
4603 }
4604 }
4605
4606 /*
4607 * Apply update log, if any, on initial load.
4608 */
4609 if (zone->journal != NULL &&
4610 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4611 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4612 {
4613 if (zone->type == dns_zone_master && (inline_secure(zone) ||
4614 (zone->update_acl != NULL || zone->ssutable != NULL)))
4615 {
4616 options = DNS_JOURNALOPT_RESIGN;
4617 } else {
4618 options = 0;
4619 }
4620 result = dns_journal_rollforward(zone->mctx, db, options,
4621 zone->journal);
4622 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
4623 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
4624 result != ISC_R_RANGE)
4625 {
4626 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4627 ISC_LOG_ERROR,
4628 "journal rollforward failed: %s",
4629 dns_result_totext(result));
4630 goto cleanup;
4631
4632
4633 }
4634 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
4635 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4636 ISC_LOG_ERROR,
4637 "journal rollforward failed: "
4638 "journal out of sync with zone");
4639 goto cleanup;
4640 }
4641 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4642 "journal rollforward completed "
4643 "successfully: %s",
4644 dns_result_totext(result));
4645 if (result == ISC_R_SUCCESS) {
4646 needdump = true;
4647 }
4648 }
4649
4650 /*
4651 * Obtain ns, soa and cname counts for top of zone.
4652 */
4653 INSIST(db != NULL);
4654 result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
4655 &refresh, &retry, &expire, &minimum,
4656 &errors);
4657 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4658 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4659 "could not find NS and/or SOA records");
4660 }
4661
4662 /*
4663 * Check to make sure the journal is up to date, and remove the
4664 * journal file if it isn't, as we wouldn't be able to apply
4665 * updates otherwise.
4666 */
4667 if (zone->journal != NULL && dns_zone_isdynamic(zone, true) &&
4668 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
4669 {
4670 uint32_t jserial;
4671 dns_journal_t *journal = NULL;
4672 bool empty = false;
4673
4674 result = dns_journal_open(zone->mctx, zone->journal,
4675 DNS_JOURNAL_READ, &journal);
4676 if (result == ISC_R_SUCCESS) {
4677 jserial = dns_journal_last_serial(journal);
4678 empty = dns_journal_empty(journal);
4679 dns_journal_destroy(&journal);
4680 } else {
4681 jserial = serial;
4682 result = ISC_R_SUCCESS;
4683 }
4684
4685 if (jserial != serial) {
4686 if (!empty) {
4687 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4688 ISC_LOG_INFO,
4689 "journal file is out of date: "
4690 "removing journal file");
4691 }
4692 if (remove(zone->journal) < 0 && errno != ENOENT) {
4693 char strbuf[ISC_STRERRORSIZE];
4694 strerror_r(errno, strbuf, sizeof(strbuf));
4695 isc_log_write(dns_lctx,
4696 DNS_LOGCATEGORY_GENERAL,
4697 DNS_LOGMODULE_ZONE,
4698 ISC_LOG_WARNING,
4699 "unable to remove journal "
4700 "'%s': '%s'",
4701 zone->journal, strbuf);
4702 }
4703 }
4704 }
4705
4706 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4707 "loaded; checking validity");
4708
4709 /*
4710 * Master / Slave / Mirror / Stub zones require both NS and SOA records
4711 * at the top of the zone.
4712 */
4713
4714 switch (zone->type) {
4715 case dns_zone_dlz:
4716 case dns_zone_master:
4717 case dns_zone_slave:
4718 case dns_zone_mirror:
4719 case dns_zone_stub:
4720 case dns_zone_redirect:
4721 if (soacount != 1) {
4722 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4723 ISC_LOG_ERROR,
4724 "has %d SOA records", soacount);
4725 result = DNS_R_BADZONE;
4726 }
4727 if (nscount == 0) {
4728 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4729 ISC_LOG_ERROR,
4730 "has no NS records");
4731 result = DNS_R_BADZONE;
4732 }
4733 if (result != ISC_R_SUCCESS) {
4734 goto cleanup;
4735 }
4736 if (zone->type == dns_zone_master && errors != 0) {
4737 result = DNS_R_BADZONE;
4738 goto cleanup;
4739 }
4740 if (zone->type != dns_zone_stub &&
4741 zone->type != dns_zone_redirect)
4742 {
4743 result = check_nsec3param(zone, db);
4744 if (result != ISC_R_SUCCESS)
4745 goto cleanup;
4746 }
4747 if (zone->type == dns_zone_master &&
4748 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4749 !integrity_checks(zone, db))
4750 {
4751 result = DNS_R_BADZONE;
4752 goto cleanup;
4753 }
4754 if (zone->type == dns_zone_master &&
4755 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4756 !zone_check_dup(zone, db))
4757 {
4758 result = DNS_R_BADZONE;
4759 goto cleanup;
4760 }
4761
4762 result = dns_zone_verifydb(zone, db, NULL);
4763 if (result != ISC_R_SUCCESS) {
4764 goto cleanup;
4765 }
4766
4767 if (zone->db != NULL) {
4768 unsigned int oldsoacount;
4769
4770 /*
4771 * This is checked in zone_replacedb() for slave zones
4772 * as they don't reload from disk.
4773 */
4774 result = zone_get_from_db(zone, zone->db, NULL,
4775 &oldsoacount, &oldserial,
4776 NULL, NULL, NULL, NULL,
4777 NULL);
4778 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4779 RUNTIME_CHECK(soacount > 0U);
4780 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4781 !isc_serial_gt(serial, oldserial)) {
4782 uint32_t serialmin, serialmax;
4783
4784 INSIST(zone->type == dns_zone_master);
4785 INSIST(zone->raw == NULL);
4786
4787 if (serial == oldserial &&
4788 zone_unchanged(zone->db, db, zone->mctx)) {
4789 dns_zone_logc(zone,
4790 DNS_LOGCATEGORY_ZONELOAD,
4791 ISC_LOG_INFO,
4792 "ixfr-from-differences: "
4793 "unchanged");
4794 goto done;
4795 }
4796
4797 serialmin = (oldserial + 1) & 0xffffffffU;
4798 serialmax = (oldserial + 0x7fffffffU) &
4799 0xffffffffU;
4800 dns_zone_logc(zone,
4801 DNS_LOGCATEGORY_ZONELOAD,
4802 ISC_LOG_ERROR,
4803 "ixfr-from-differences: "
4804 "new serial (%u) out of range "
4805 "[%u - %u]", serial, serialmin,
4806 serialmax);
4807 result = DNS_R_BADZONE;
4808 goto cleanup;
4809 } else if (!isc_serial_ge(serial, oldserial)) {
4810 dns_zone_logc(zone,
4811 DNS_LOGCATEGORY_ZONELOAD,
4812 ISC_LOG_ERROR,
4813 "zone serial (%u/%u) has gone "
4814 "backwards", serial, oldserial);
4815 } else if (serial == oldserial && !hasinclude &&
4816 strcmp(zone->db_argv[0], "_builtin") != 0)
4817 {
4818 dns_zone_logc(zone,
4819 DNS_LOGCATEGORY_ZONELOAD,
4820 ISC_LOG_ERROR,
4821 "zone serial (%u) unchanged. "
4822 "zone may fail to transfer "
4823 "to slaves.", serial);
4824 }
4825 }
4826
4827 if (zone->type == dns_zone_master &&
4828 (zone->update_acl != NULL || zone->ssutable != NULL) &&
4829 zone->sigresigninginterval < (3 * refresh) &&
4830 dns_db_issecure(db))
4831 {
4832 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4833 ISC_LOG_WARNING,
4834 "sig-re-signing-interval less than "
4835 "3 * refresh.");
4836 }
4837
4838 zone->refresh = RANGE(refresh,
4839 zone->minrefresh, zone->maxrefresh);
4840 zone->retry = RANGE(retry,
4841 zone->minretry, zone->maxretry);
4842 zone->expire = RANGE(expire, zone->refresh + zone->retry,
4843 DNS_MAX_EXPIRE);
4844 zone->minimum = minimum;
4845 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4846
4847 if (zone->type == dns_zone_slave ||
4848 zone->type == dns_zone_mirror ||
4849 zone->type == dns_zone_stub ||
4850 (zone->type == dns_zone_redirect &&
4851 zone->masters != NULL))
4852 {
4853 isc_time_t t;
4854 uint32_t delay;
4855
4856 result = isc_file_getmodtime(zone->journal, &t);
4857 if (result != ISC_R_SUCCESS) {
4858 result = isc_file_getmodtime(zone->masterfile,
4859 &t);
4860 }
4861 if (result == ISC_R_SUCCESS) {
4862 DNS_ZONE_TIME_ADD(&t, zone->expire,
4863 &zone->expiretime);
4864 } else {
4865 DNS_ZONE_TIME_ADD(&now, zone->retry,
4866 &zone->expiretime);
4867 }
4868
4869 delay = (zone->retry -
4870 isc_random_uniform((zone->retry * 3) / 4));
4871 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4872 if (isc_time_compare(&zone->refreshtime,
4873 &zone->expiretime) >= 0)
4874 {
4875 zone->refreshtime = now;
4876 }
4877 }
4878
4879 break;
4880
4881 case dns_zone_key:
4882 result = sync_keyzone(zone, db);
4883 if (result != ISC_R_SUCCESS) {
4884 goto cleanup;
4885 }
4886 break;
4887
4888 default:
4889 UNEXPECTED_ERROR(__FILE__, __LINE__,
4890 "unexpected zone type %d", zone->type);
4891 result = ISC_R_UNEXPECTED;
4892 goto cleanup;
4893 }
4894
4895 /*
4896 * Check for weak DNSKEY's.
4897 */
4898 if (zone->type == dns_zone_master) {
4899 zone_check_dnskeys(zone, db);
4900 }
4901
4902 /*
4903 * Schedule DNSSEC key refresh.
4904 */
4905 if (zone->type == dns_zone_master &&
4906 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4907 {
4908 zone->refreshkeytime = now;
4909 }
4910
4911 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4912 if (zone->db != NULL) {
4913 had_db = true;
4914 result = zone_replacedb(zone, db, false);
4915 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4916 if (result != ISC_R_SUCCESS) {
4917 goto cleanup;
4918 }
4919 } else {
4920 zone_attachdb(zone, db);
4921 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4922 DNS_ZONE_SETFLAG(zone,
4923 DNS_ZONEFLG_LOADED|
4924 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
4925 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4926 inline_raw(zone))
4927 {
4928 if (zone->secure->db == NULL) {
4929 zone_send_securedb(zone, db);
4930 } else {
4931 zone_send_secureserial(zone, serial);
4932 }
4933 }
4934 }
4935
4936 /*
4937 * Finished loading inline-signing zone; need to get status
4938 * from the raw side now.
4939 */
4940 if (zone->type == dns_zone_master && inline_secure(zone)) {
4941 maybe_send_secure(zone);
4942 }
4943
4944 result = ISC_R_SUCCESS;
4945
4946 if (needdump) {
4947 if (zone->type == dns_zone_key) {
4948 zone_needdump(zone, 30);
4949 } else {
4950 zone_needdump(zone, DNS_DUMP_DELAY);
4951 }
4952 }
4953
4954 if (zone->task != NULL) {
4955 if (zone->type == dns_zone_master) {
4956 set_resigntime(zone);
4957 resume_signingwithkey(zone);
4958 resume_addnsec3chain(zone);
4959 }
4960
4961 if (zone->type == dns_zone_master &&
4962 !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4963 dns_zone_isdynamic(zone, false) &&
4964 dns_db_issecure(db))
4965 {
4966 dns_name_t *name;
4967 dns_fixedname_t fixed;
4968 dns_rdataset_t next;
4969
4970 dns_rdataset_init(&next);
4971 name = dns_fixedname_initname(&fixed);
4972
4973 result = dns_db_getsigningtime(db, &next, name);
4974 if (result == ISC_R_SUCCESS) {
4975 isc_stdtime_t timenow;
4976 char namebuf[DNS_NAME_FORMATSIZE];
4977 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4978
4979 isc_stdtime_get(&timenow);
4980 dns_name_format(name, namebuf, sizeof(namebuf));
4981 dns_rdatatype_format(next.covers,
4982 typebuf, sizeof(typebuf));
4983 dnssec_log(zone, ISC_LOG_DEBUG(3),
4984 "next resign: %s/%s "
4985 "in %d seconds", namebuf, typebuf,
4986 next.resign - timenow -
4987 zone->sigresigninginterval);
4988 dns_rdataset_disassociate(&next);
4989 } else {
4990 dnssec_log(zone, ISC_LOG_WARNING,
4991 "signed dynamic zone has no "
4992 "resign event scheduled");
4993 }
4994 }
4995
4996 zone_settimer(zone, &now);
4997 }
4998
4999 /*
5000 * Clear old include list.
5001 */
5002 for (inc = ISC_LIST_HEAD(zone->includes);
5003 inc != NULL;
5004 inc = ISC_LIST_HEAD(zone->includes))
5005 {
5006 ISC_LIST_UNLINK(zone->includes, inc, link);
5007 isc_mem_free(zone->mctx, inc->name);
5008 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5009 }
5010 zone->nincludes = 0;
5011
5012 /*
5013 * Transfer new include list.
5014 */
5015 for (inc = ISC_LIST_HEAD(zone->newincludes);
5016 inc != NULL;
5017 inc = ISC_LIST_HEAD(zone->newincludes))
5018 {
5019 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5020 ISC_LIST_APPEND(zone->includes, inc, link);
5021 zone->nincludes++;
5022 }
5023
5024 if (! dns_db_ispersistent(db)) {
5025 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5026 ISC_LOG_INFO, "loaded serial %u%s", serial,
5027 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5028 }
5029
5030 if (!had_db && zone->type == dns_zone_mirror) {
5031 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5032 "mirror zone is now in use");
5033 }
5034
5035 zone->loadtime = loadtime;
5036 goto done;
5037
5038 cleanup:
5039 if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
5040 dnssec_log(zone, ISC_LOG_ERROR,
5041 "failed to initialize managed-keys (%s): "
5042 "DNSSEC validation is at risk",
5043 isc_result_totext(result));
5044 }
5045
5046 for (inc = ISC_LIST_HEAD(zone->newincludes);
5047 inc != NULL;
5048 inc = ISC_LIST_HEAD(zone->newincludes))
5049 {
5050 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5051 isc_mem_free(zone->mctx, inc->name);
5052 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5053 }
5054 if (zone->type == dns_zone_slave ||
5055 zone->type == dns_zone_mirror ||
5056 zone->type == dns_zone_stub ||
5057 zone->type == dns_zone_key ||
5058 (zone->type == dns_zone_redirect && zone->masters != NULL))
5059 {
5060 if (result != ISC_R_NOMEMORY) {
5061 if (zone->journal != NULL) {
5062 zone_saveunique(zone, zone->journal,
5063 "jn-XXXXXXXX");
5064 }
5065 if (zone->masterfile != NULL) {
5066 zone_saveunique(zone, zone->masterfile,
5067 "db-XXXXXXXX");
5068 }
5069 }
5070
5071 /* Mark the zone for immediate refresh. */
5072 zone->refreshtime = now;
5073 if (zone->task != NULL) {
5074 zone_settimer(zone, &now);
5075 }
5076 result = ISC_R_SUCCESS;
5077 } else if (zone->type == dns_zone_master ||
5078 zone->type == dns_zone_redirect)
5079 {
5080 if (! (inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5081 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5082 ISC_LOG_ERROR,
5083 "not loaded due to errors.");
5084 } else if (zone->type == dns_zone_master) {
5085 result = ISC_R_SUCCESS;
5086 }
5087 }
5088
5089 done:
5090 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5091 /*
5092 * If this is an inline-signed zone and we were called for the raw
5093 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5094 * as well, but only if this is a reload, not an initial zone load: in
5095 * the former case, zone_postload() will not be run for the secure
5096 * zone; in the latter case, it will be. Check which case we are
5097 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5098 * secure zone: if it is set, this must be a reload.
5099 */
5100 if (inline_raw(zone) &&
5101 DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5102 {
5103 DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5104 }
5105
5106 zone_debuglog(zone, "zone_postload", 99, "done");
5107
5108 return (result);
5109}
5110
5111static bool
5112exit_check(dns_zone_t *zone) {
5113 REQUIRE(LOCKED_ZONE(zone));
5114
5115 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
5116 /*
5117 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5118 */
5119 INSIST(isc_refcount_current(&zone->erefs) == 0);
5120 return (true);
5121 }
5122 return (false);
5123}
5124
5125static bool
5126zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5127 dns_name_t *name, bool logit)
5128{
5129 isc_result_t result;
5130 char namebuf[DNS_NAME_FORMATSIZE];
5131 char altbuf[DNS_NAME_FORMATSIZE];
5132 dns_fixedname_t fixed;
5133 dns_name_t *foundname;
5134 int level;
5135
5136 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
5137 return (true);
5138
5139 if (zone->type == dns_zone_master)
5140 level = ISC_LOG_ERROR;
5141 else
5142 level = ISC_LOG_WARNING;
5143
5144 foundname = dns_fixedname_initname(&fixed);
5145
5146 result = dns_db_find(db, name, version, dns_rdatatype_a,
5147 0, 0, NULL, foundname, NULL, NULL);
5148 if (result == ISC_R_SUCCESS)
5149 return (true);
5150
5151 if (result == DNS_R_NXRRSET) {
5152 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
5153 0, 0, NULL, foundname, NULL, NULL);
5154 if (result == ISC_R_SUCCESS)
5155 return (true);
5156 }
5157
5158 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5159 result == DNS_R_EMPTYNAME) {
5160 if (logit) {
5161 dns_name_format(name, namebuf, sizeof namebuf);
5162 dns_zone_log(zone, level, "NS '%s' has no address "
5163 "records (A or AAAA)", namebuf);
5164 }
5165 return (false);
5166 }
5167
5168 if (result == DNS_R_CNAME) {
5169 if (logit) {
5170 dns_name_format(name, namebuf, sizeof namebuf);
5171 dns_zone_log(zone, level, "NS '%s' is a CNAME "
5172 "(illegal)", namebuf);
5173 }
5174 return (false);
5175 }
5176
5177 if (result == DNS_R_DNAME) {
5178 if (logit) {
5179 dns_name_format(name, namebuf, sizeof namebuf);
5180 dns_name_format(foundname, altbuf, sizeof altbuf);
5181 dns_zone_log(zone, level, "NS '%s' is below a DNAME "
5182 "'%s' (illegal)", namebuf, altbuf);
5183 }
5184 return (false);
5185 }
5186
5187 return (true);
5188}
5189
5190static isc_result_t
5191zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5192 dns_dbversion_t *version, unsigned int *nscount,
5193 unsigned int *errors, bool logit)
5194{
5195 isc_result_t result;
5196 unsigned int count = 0;
5197 unsigned int ecount = 0;
5198 dns_rdataset_t rdataset;
5199 dns_rdata_t rdata;
5200 dns_rdata_ns_t ns;
5201
5202 dns_rdataset_init(&rdataset);
5203 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5204 dns_rdatatype_none, 0, &rdataset, NULL);
5205 if (result == ISC_R_NOTFOUND) {
5206 INSIST(!dns_rdataset_isassociated(&rdataset));
5207 goto success;
5208 }
5209 if (result != ISC_R_SUCCESS) {
5210 INSIST(!dns_rdataset_isassociated(&rdataset));
5211 goto invalidate_rdataset;
5212 }
5213
5214 result = dns_rdataset_first(&rdataset);
5215 while (result == ISC_R_SUCCESS) {
5216 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5217 (zone->type == dns_zone_master ||
5218 zone->type == dns_zone_slave ||
5219 zone->type == dns_zone_mirror))
5220 {
5221 dns_rdata_init(&rdata);
5222 dns_rdataset_current(&rdataset, &rdata);
5223 result = dns_rdata_tostruct(&rdata, &ns, NULL);
5224 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5225 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5226 !zone_check_ns(zone, db, version, &ns.name, logit))
5227 ecount++;
5228 }
5229 count++;
5230 result = dns_rdataset_next(&rdataset);
5231 }
5232 dns_rdataset_disassociate(&rdataset);
5233
5234 success:
5235 if (nscount != NULL)
5236 *nscount = count;
5237 if (errors != NULL)
5238 *errors = ecount;
5239
5240 result = ISC_R_SUCCESS;
5241
5242 invalidate_rdataset:
5243 dns_rdataset_invalidate(&rdataset);
5244
5245 return (result);
5246}
5247
5248static isc_result_t
5249zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5250 unsigned int *soacount,
5251 uint32_t *serial, uint32_t *refresh,
5252 uint32_t *retry, uint32_t *expire,
5253 uint32_t *minimum)
5254{
5255 isc_result_t result;
5256 unsigned int count;
5257 dns_rdataset_t rdataset;
5258 dns_rdata_t rdata = DNS_RDATA_INIT;
5259 dns_rdata_soa_t soa;
5260
5261 dns_rdataset_init(&rdataset);
5262 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5263 dns_rdatatype_none, 0, &rdataset, NULL);
5264 if (result == ISC_R_NOTFOUND) {
5265 INSIST(!dns_rdataset_isassociated(&rdataset));
5266 if (soacount != NULL)
5267 *soacount = 0;
5268 if (serial != NULL)
5269 *serial = 0;
5270 if (refresh != NULL)
5271 *refresh = 0;
5272 if (retry != NULL)
5273 *retry = 0;
5274 if (expire != NULL)
5275 *expire = 0;
5276 if (minimum != NULL)
5277 *minimum = 0;
5278 result = ISC_R_SUCCESS;
5279 goto invalidate_rdataset;
5280 }
5281 if (result != ISC_R_SUCCESS) {
5282 INSIST(!dns_rdataset_isassociated(&rdataset));
5283 goto invalidate_rdataset;
5284 }
5285
5286 count = 0;
5287 result = dns_rdataset_first(&rdataset);
5288 while (result == ISC_R_SUCCESS) {
5289 dns_rdata_init(&rdata);
5290 dns_rdataset_current(&rdataset, &rdata);
5291 count++;
5292 if (count == 1) {
5293 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5294 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5295 }
5296
5297 result = dns_rdataset_next(&rdataset);
5298 dns_rdata_reset(&rdata);
5299 }
5300 dns_rdataset_disassociate(&rdataset);
5301
5302 if (soacount != NULL)
5303 *soacount = count;
5304
5305 if (count > 0) {
5306 if (serial != NULL)
5307 *serial = soa.serial;
5308 if (refresh != NULL)
5309 *refresh = soa.refresh;
5310 if (retry != NULL)
5311 *retry = soa.retry;
5312 if (expire != NULL)
5313 *expire = soa.expire;
5314 if (minimum != NULL)
5315 *minimum = soa.minimum;
5316 } else {
5317 if (soacount != NULL)
5318 *soacount = 0;
5319 if (serial != NULL)
5320 *serial = 0;
5321 if (refresh != NULL)
5322 *refresh = 0;
5323 if (retry != NULL)
5324 *retry = 0;
5325 if (expire != NULL)
5326 *expire = 0;
5327 if (minimum != NULL)
5328 *minimum = 0;
5329 }
5330
5331 result = ISC_R_SUCCESS;
5332
5333 invalidate_rdataset:
5334 dns_rdataset_invalidate(&rdataset);
5335
5336 return (result);
5337}
5338
5339/*
5340 * zone must be locked.
5341 */
5342static isc_result_t
5343zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5344 unsigned int *soacount, uint32_t *serial,
5345 uint32_t *refresh, uint32_t *retry,
5346 uint32_t *expire, uint32_t *minimum,
5347 unsigned int *errors)
5348{
5349 isc_result_t result;
5350 isc_result_t answer = ISC_R_SUCCESS;
5351 dns_dbversion_t *version = NULL;
5352 dns_dbnode_t *node;
5353
5354 REQUIRE(db != NULL);
5355 REQUIRE(zone != NULL);
5356
5357 dns_db_currentversion(db, &version);
5358
5359 if (nscount != NULL)
5360 *nscount = 0;
5361 if (soacount != NULL)
5362 *soacount = 0;
5363 if (serial != NULL)
5364 *serial = 0;
5365 if (refresh != NULL)
5366 *refresh = 0;
5367 if (retry != NULL)
5368 *retry = 0;
5369 if (expire != NULL)
5370 *expire = 0;
5371 if (errors != NULL)
5372 *errors = 0;
5373
5374 node = NULL;
5375 result = dns_db_findnode(db, &zone->origin, false, &node);
5376 if (result != ISC_R_SUCCESS) {
5377 answer = result;
5378 goto closeversion;
5379 }
5380
5381 if (nscount != NULL || errors != NULL) {
5382 result = zone_count_ns_rr(zone, db, node, version,
5383 nscount, errors, true);
5384 if (result != ISC_R_SUCCESS)
5385 answer = result;
5386 }
5387
5388 if (soacount != NULL || serial != NULL || refresh != NULL
5389 || retry != NULL || expire != NULL || minimum != NULL) {
5390 result = zone_load_soa_rr(db, node, version, soacount,
5391 serial, refresh, retry, expire,
5392 minimum);
5393 if (result != ISC_R_SUCCESS)
5394 answer = result;
5395 }
5396
5397 dns_db_detachnode(db, &node);
5398 closeversion:
5399 dns_db_closeversion(db, &version, false);
5400
5401 return (answer);
5402}
5403
5404void
5405dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5406 REQUIRE(DNS_ZONE_VALID(source));
5407 REQUIRE(target != NULL && *target == NULL);
5408 isc_refcount_increment(&source->erefs);
5409 *target = source;
5410}
5411
5412void
5413dns_zone_detach(dns_zone_t **zonep) {
5414 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5415 dns_zone_t *zone = *zonep;
5416 *zonep = NULL;
5417
5418 bool free_now = false;
5419 dns_zone_t *raw = NULL;
5420 dns_zone_t *secure = NULL;
5421 if (isc_refcount_decrement(&zone->erefs) == 1) {
5422 isc_refcount_destroy(&zone->erefs);
5423
5424 LOCK_ZONE(zone);
5425 INSIST(zone != zone->raw);
5426 /*
5427 * We just detached the last external reference.
5428 */
5429 if (zone->task != NULL) {
5430 /*
5431 * This zone is being managed. Post
5432 * its control event and let it clean
5433 * up synchronously in the context of
5434 * its task.
5435 */
5436 isc_event_t *ev = &zone->ctlevent;
5437 isc_task_send(zone->task, &ev);
5438 } else {
5439 /*
5440 * This zone is not being managed; it has
5441 * no task and can have no outstanding
5442 * events. Free it immediately.
5443 */
5444 /*
5445 * Unmanaged zones should not have non-null views;
5446 * we have no way of detaching from the view here
5447 * without causing deadlock because this code is called
5448 * with the view already locked.
5449 */
5450 INSIST(zone->view == NULL);
5451 free_now = true;
5452 raw = zone->raw;
5453 zone->raw = NULL;
5454 secure = zone->secure;
5455 zone->secure = NULL;
5456 }
5457 UNLOCK_ZONE(zone);
5458 }
5459 if (free_now) {
5460 if (raw != NULL) {
5461 dns_zone_detach(&raw);
5462 }
5463 if (secure != NULL) {
5464 dns_zone_idetach(&secure);
5465 }
5466 zone_free(zone);
5467 }
5468}
5469
5470void
5471dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5472 REQUIRE(DNS_ZONE_VALID(source));
5473 REQUIRE(target != NULL && *target == NULL);
5474 LOCK_ZONE(source);
5475 zone_iattach(source, target);
5476 UNLOCK_ZONE(source);
5477}
5478
5479static void
5480zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5481
5482 /*
5483 * 'source' locked by caller.
5484 */
5485 REQUIRE(LOCKED_ZONE(source));
5486 REQUIRE(DNS_ZONE_VALID(source));
5487 REQUIRE(target != NULL && *target == NULL);
5488 INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
5489 source->irefs++;
5490 INSIST(source->irefs != 0);
5491 *target = source;
5492}
5493
5494static void
5495zone_idetach(dns_zone_t **zonep) {
5496 dns_zone_t *zone;
5497
5498 /*
5499 * 'zone' locked by caller.
5500 */
5501 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5502 zone = *zonep;
5503 REQUIRE(LOCKED_ZONE(*zonep));
5504 *zonep = NULL;
5505
5506 INSIST(zone->irefs > 0);
5507 zone->irefs--;
5508 INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
5509}
5510
5511void
5512dns_zone_idetach(dns_zone_t **zonep) {
5513 dns_zone_t *zone;
5514 bool free_needed;
5515
5516 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5517 zone = *zonep;
5518 *zonep = NULL;
5519
5520 LOCK_ZONE(zone);
5521 INSIST(zone->irefs > 0);
5522 zone->irefs--;
5523 free_needed = exit_check(zone);
5524 UNLOCK_ZONE(zone);
5525 if (free_needed)
5526 zone_free(zone);
5527}
5528
5529isc_mem_t *
5530dns_zone_getmctx(dns_zone_t *zone) {
5531 REQUIRE(DNS_ZONE_VALID(zone));
5532
5533 return (zone->mctx);
5534}
5535
5536dns_zonemgr_t *
5537dns_zone_getmgr(dns_zone_t *zone) {
5538 REQUIRE(DNS_ZONE_VALID(zone));
5539
5540 return (zone->zmgr);
5541}
5542
5543void
5544dns_zone_setflag(dns_zone_t *zone, unsigned int flags, bool value) {
5545 REQUIRE(DNS_ZONE_VALID(zone));
5546
5547 LOCK_ZONE(zone);
5548 if (value)
5549 DNS_ZONE_SETFLAG(zone, flags);
5550 else
5551 DNS_ZONE_CLRFLAG(zone, flags);
5552 UNLOCK_ZONE(zone);
5553}
5554
5555void
5556dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option,
5557 bool value)
5558{
5559 REQUIRE(DNS_ZONE_VALID(zone));
5560
5561 LOCK_ZONE(zone);
5562 if (value)
5563 zone->options |= option;
5564 else
5565 zone->options &= ~option;
5566 UNLOCK_ZONE(zone);
5567}
5568
5569dns_zoneopt_t
5570dns_zone_getoptions(dns_zone_t *zone) {
5571 REQUIRE(DNS_ZONE_VALID(zone));
5572
5573 return (zone->options);
5574}
5575
5576void
5577dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value)
5578{
5579 REQUIRE(DNS_ZONE_VALID(zone));
5580
5581 LOCK_ZONE(zone);
5582 if (value)
5583 zone->keyopts |= keyopt;
5584 else
5585 zone->keyopts &= ~keyopt;
5586 UNLOCK_ZONE(zone);
5587}
5588
5589unsigned int
5590dns_zone_getkeyopts(dns_zone_t *zone) {
5591
5592 REQUIRE(DNS_ZONE_VALID(zone));
5593
5594 return (zone->keyopts);
5595}
5596
5597isc_result_t
5598dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5599 REQUIRE(DNS_ZONE_VALID(zone));
5600
5601 LOCK_ZONE(zone);
5602 zone->xfrsource4 = *xfrsource;
5603 UNLOCK_ZONE(zone);
5604
5605 return (ISC_R_SUCCESS);
5606}
5607
5608isc_sockaddr_t *
5609dns_zone_getxfrsource4(dns_zone_t *zone) {
5610 REQUIRE(DNS_ZONE_VALID(zone));
5611 return (&zone->xfrsource4);
5612}
5613
5614isc_result_t
5615dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5616 REQUIRE(DNS_ZONE_VALID(zone));
5617
5618 LOCK_ZONE(zone);
5619 zone->xfrsource4dscp = dscp;
5620 UNLOCK_ZONE(zone);
5621
5622 return (ISC_R_SUCCESS);
5623}
5624
5625isc_dscp_t
5626dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5627 REQUIRE(DNS_ZONE_VALID(zone));
5628 return (zone->xfrsource4dscp);
5629}
5630
5631isc_result_t
5632dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5633 REQUIRE(DNS_ZONE_VALID(zone));
5634
5635 LOCK_ZONE(zone);
5636 zone->xfrsource6 = *xfrsource;
5637 UNLOCK_ZONE(zone);
5638
5639 return (ISC_R_SUCCESS);
5640}
5641
5642isc_sockaddr_t *
5643dns_zone_getxfrsource6(dns_zone_t *zone) {
5644 REQUIRE(DNS_ZONE_VALID(zone));
5645 return (&zone->xfrsource6);
5646}
5647
5648isc_dscp_t
5649dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5650 REQUIRE(DNS_ZONE_VALID(zone));
5651 return (zone->xfrsource6dscp);
5652}
5653
5654isc_result_t
5655dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5656 REQUIRE(DNS_ZONE_VALID(zone));
5657
5658 LOCK_ZONE(zone);
5659 zone->xfrsource6dscp = dscp;
5660 UNLOCK_ZONE(zone);
5661
5662 return (ISC_R_SUCCESS);
5663}
5664
5665isc_result_t
5666dns_zone_setaltxfrsource4(dns_zone_t *zone,
5667 const isc_sockaddr_t *altxfrsource)
5668{
5669 REQUIRE(DNS_ZONE_VALID(zone));
5670
5671 LOCK_ZONE(zone);
5672 zone->altxfrsource4 = *altxfrsource;
5673 UNLOCK_ZONE(zone);
5674
5675 return (ISC_R_SUCCESS);
5676}
5677
5678isc_sockaddr_t *
5679dns_zone_getaltxfrsource4(dns_zone_t *zone) {
5680 REQUIRE(DNS_ZONE_VALID(zone));
5681 return (&zone->altxfrsource4);
5682}
5683
5684isc_result_t
5685dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5686 REQUIRE(DNS_ZONE_VALID(zone));
5687
5688 LOCK_ZONE(zone);
5689 zone->altxfrsource4dscp = dscp;
5690 UNLOCK_ZONE(zone);
5691
5692 return (ISC_R_SUCCESS);
5693}
5694
5695isc_dscp_t
5696dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
5697 REQUIRE(DNS_ZONE_VALID(zone));
5698 return (zone->altxfrsource4dscp);
5699}
5700
5701isc_result_t
5702dns_zone_setaltxfrsource6(dns_zone_t *zone,
5703 const isc_sockaddr_t *altxfrsource)
5704{
5705 REQUIRE(DNS_ZONE_VALID(zone));
5706
5707 LOCK_ZONE(zone);
5708 zone->altxfrsource6 = *altxfrsource;
5709 UNLOCK_ZONE(zone);
5710
5711 return (ISC_R_SUCCESS);
5712}
5713
5714isc_sockaddr_t *
5715dns_zone_getaltxfrsource6(dns_zone_t *zone) {
5716 REQUIRE(DNS_ZONE_VALID(zone));
5717 return (&zone->altxfrsource6);
5718}
5719
5720isc_result_t
5721dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5722 REQUIRE(DNS_ZONE_VALID(zone));
5723
5724 LOCK_ZONE(zone);
5725 zone->altxfrsource6dscp = dscp;
5726 UNLOCK_ZONE(zone);
5727
5728 return (ISC_R_SUCCESS);
5729}
5730
5731isc_dscp_t
5732dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
5733 REQUIRE(DNS_ZONE_VALID(zone));
5734 return (zone->altxfrsource6dscp);
5735}
5736
5737isc_result_t
5738dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5739 REQUIRE(DNS_ZONE_VALID(zone));
5740
5741 LOCK_ZONE(zone);
5742 zone->notifysrc4 = *notifysrc;
5743 UNLOCK_ZONE(zone);
5744
5745 return (ISC_R_SUCCESS);
5746}
5747
5748isc_sockaddr_t *
5749dns_zone_getnotifysrc4(dns_zone_t *zone) {
5750 REQUIRE(DNS_ZONE_VALID(zone));
5751 return (&zone->notifysrc4);
5752}
5753
5754isc_result_t
5755dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5756 REQUIRE(DNS_ZONE_VALID(zone));
5757
5758 LOCK_ZONE(zone);
5759 zone->notifysrc4dscp = dscp;
5760 UNLOCK_ZONE(zone);
5761
5762 return (ISC_R_SUCCESS);
5763}
5764
5765isc_dscp_t
5766dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
5767 REQUIRE(DNS_ZONE_VALID(zone));
5768 return (zone->notifysrc4dscp);
5769}
5770
5771isc_result_t
5772dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5773 REQUIRE(DNS_ZONE_VALID(zone));
5774
5775 LOCK_ZONE(zone);
5776 zone->notifysrc6 = *notifysrc;
5777 UNLOCK_ZONE(zone);
5778
5779 return (ISC_R_SUCCESS);
5780}
5781
5782isc_sockaddr_t *
5783dns_zone_getnotifysrc6(dns_zone_t *zone) {
5784 REQUIRE(DNS_ZONE_VALID(zone));
5785 return (&zone->notifysrc6);
5786}
5787
5788static bool
5789same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
5790 uint32_t count)
5791{
5792 unsigned int i;
5793
5794 for (i = 0; i < count; i++)
5795 if (!isc_sockaddr_equal(&oldlist[i], &newlist[i]))
5796 return (false);
5797 return (true);
5798}
5799
5800static bool
5801same_keynames(dns_name_t * const *oldlist, dns_name_t * const *newlist,
5802 uint32_t count)
5803{
5804 unsigned int i;
5805
5806 if (oldlist == NULL && newlist == NULL)
5807 return (true);
5808 if (oldlist == NULL || newlist == NULL)
5809 return (false);
5810
5811 for (i = 0; i < count; i++) {
5812 if (oldlist[i] == NULL && newlist[i] == NULL)
5813 continue;
5814 if (oldlist[i] == NULL || newlist[i] == NULL ||
5815 !dns_name_equal(oldlist[i], newlist[i]))
5816 return (false);
5817 }
5818 return (true);
5819}
5820
5821static void
5822clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
5823 dns_name_t ***keynamesp, unsigned int *countp,
5824 isc_mem_t *mctx)
5825{
5826 unsigned int count;
5827 isc_sockaddr_t *addrs;
5828 isc_dscp_t *dscps;
5829 dns_name_t **keynames;
5830
5831 REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
5832 keynamesp != NULL);
5833
5834 count = *countp;
5835 *countp = 0;
5836 addrs = *addrsp;
5837 *addrsp = NULL;
5838 dscps = *dscpsp;
5839 *dscpsp = NULL;
5840 keynames = *keynamesp;
5841 *keynamesp = NULL;
5842
5843 if (addrs != NULL)
5844 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
5845
5846 if (dscps != NULL)
5847 isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
5848
5849 if (keynames != NULL) {
5850 unsigned int i;
5851 for (i = 0; i < count; i++) {
5852 if (keynames[i] != NULL) {
5853 dns_name_free(keynames[i], mctx);
5854 isc_mem_put(mctx, keynames[i],
5855 sizeof(dns_name_t));
5856 keynames[i] = NULL;
5857 }
5858 }
5859 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
5860 }
5861}
5862
5863static isc_result_t
5864set_addrkeylist(unsigned int count,
5865 const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
5866 const isc_dscp_t *dscp, isc_dscp_t **newdscpp,
5867 dns_name_t **names, dns_name_t ***newnamesp,
5868 isc_mem_t *mctx)
5869{
5870 isc_result_t result;
5871 isc_sockaddr_t *newaddrs = NULL;
5872 isc_dscp_t *newdscp = NULL;
5873 dns_name_t **newnames = NULL;
5874 unsigned int i;
5875
5876 REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
5877 REQUIRE(newdscpp != NULL && *newdscpp == NULL);
5878 REQUIRE(newnamesp != NULL && *newnamesp == NULL);
5879
5880 newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
5881 if (newaddrs == NULL)
5882 return (ISC_R_NOMEMORY);
5883 memmove(newaddrs, addrs, count * sizeof(*newaddrs));
5884
5885 if (dscp != NULL) {
5886 newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
5887 if (newdscp == NULL) {
5888 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5889 return (ISC_R_NOMEMORY);
5890 }
5891 memmove(newdscp, dscp, count * sizeof(*newdscp));
5892 } else
5893 newdscp = NULL;
5894
5895 if (names != NULL) {
5896 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
5897 if (newnames == NULL) {
5898 if (newdscp != NULL)
5899 isc_mem_put(mctx, newdscp,
5900 count * sizeof(*newdscp));
5901 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5902 return (ISC_R_NOMEMORY);
5903 }
5904 for (i = 0; i < count; i++)
5905 newnames[i] = NULL;
5906 for (i = 0; i < count; i++) {
5907 if (names[i] != NULL) {
5908 newnames[i] = isc_mem_get(mctx,
5909 sizeof(dns_name_t));
5910 if (newnames[i] == NULL)
5911 goto allocfail;
5912 dns_name_init(newnames[i], NULL);
5913 result = dns_name_dup(names[i], mctx,
5914 newnames[i]);
5915 if (result != ISC_R_SUCCESS) {
5916 allocfail:
5917 for (i = 0; i < count; i++)
5918 if (newnames[i] != NULL)
5919 dns_name_free(
5920 newnames[i],
5921 mctx);
5922 isc_mem_put(mctx, newaddrs,
5923 count * sizeof(*newaddrs));
5924 isc_mem_put(mctx, newdscp,
5925 count * sizeof(*newdscp));
5926 isc_mem_put(mctx, newnames,
5927 count * sizeof(*newnames));
5928 return (ISC_R_NOMEMORY);
5929 }
5930 }
5931 }
5932 } else
5933 newnames = NULL;
5934
5935 *newdscpp = newdscp;
5936 *newaddrsp = newaddrs;
5937 *newnamesp = newnames;
5938 return (ISC_R_SUCCESS);
5939}
5940
5941isc_result_t
5942dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5943 REQUIRE(DNS_ZONE_VALID(zone));
5944
5945 LOCK_ZONE(zone);
5946 zone->notifysrc6dscp = dscp;
5947 UNLOCK_ZONE(zone);
5948
5949 return (ISC_R_SUCCESS);
5950}
5951
5952isc_dscp_t
5953dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
5954 REQUIRE(DNS_ZONE_VALID(zone));
5955 return (zone->notifysrc6dscp);
5956}
5957
5958isc_result_t
5959dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
5960 uint32_t count)
5961{
5962 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
5963 count));
5964}
5965
5966isc_result_t
5967dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5968 dns_name_t **keynames, uint32_t count)
5969{
5970 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
5971 count));
5972}
5973
5974isc_result_t
5975dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5976 const isc_dscp_t *dscps, dns_name_t **keynames,
5977 uint32_t count)
5978{
5979 isc_result_t result;
5980 isc_sockaddr_t *newaddrs = NULL;
5981 isc_dscp_t *newdscps = NULL;
5982 dns_name_t **newnames = NULL;
5983
5984 REQUIRE(DNS_ZONE_VALID(zone));
5985 REQUIRE(count == 0 || notify != NULL);
5986 if (keynames != NULL)
5987 REQUIRE(count != 0);
5988
5989 LOCK_ZONE(zone);
5990
5991 if (count == zone->notifycnt &&
5992 same_addrs(zone->notify, notify, count) &&
5993 same_keynames(zone->notifykeynames, keynames, count))
5994 goto unlock;
5995
5996 clear_addresskeylist(&zone->notify, &zone->notifydscp,
5997 &zone->notifykeynames, &zone->notifycnt,
5998 zone->mctx);
5999
6000 if (count == 0)
6001 goto unlock;
6002
6003 /*
6004 * Set up the notify and notifykey lists
6005 */
6006 result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
6007 keynames, &newnames, zone->mctx);
6008 if (result != ISC_R_SUCCESS)
6009 goto unlock;
6010
6011 /*
6012 * Everything is ok so attach to the zone.
6013 */
6014 zone->notify = newaddrs;
6015 zone->notifydscp = newdscps;
6016 zone->notifykeynames = newnames;
6017 zone->notifycnt = count;
6018 unlock:
6019 UNLOCK_ZONE(zone);
6020 return (ISC_R_SUCCESS);
6021}
6022
6023isc_result_t
6024dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
6025 uint32_t count)
6026{
6027 isc_result_t result;
6028
6029 result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
6030 return (result);
6031}
6032
6033isc_result_t
6034dns_zone_setmasterswithkeys(dns_zone_t *zone,
6035 const isc_sockaddr_t *masters,
6036 dns_name_t **keynames,
6037 uint32_t count)
6038{
6039 isc_result_t result = ISC_R_SUCCESS;
6040 isc_sockaddr_t *newaddrs = NULL;
6041 isc_dscp_t *newdscps = NULL;
6042 dns_name_t **newnames = NULL;
6043 bool *newok;
6044 unsigned int i;
6045
6046 REQUIRE(DNS_ZONE_VALID(zone));
6047 REQUIRE(count == 0 || masters != NULL);
6048 if (keynames != NULL) {
6049 REQUIRE(count != 0);
6050 }
6051
6052 LOCK_ZONE(zone);
6053 /*
6054 * The refresh code assumes that 'masters' wouldn't change under it.
6055 * If it will change then kill off any current refresh in progress
6056 * and update the masters info. If it won't change then we can just
6057 * unlock and exit.
6058 */
6059 if (count != zone->masterscnt ||
6060 !same_addrs(zone->masters, masters, count) ||
6061 !same_keynames(zone->masterkeynames, keynames, count)) {
6062 if (zone->request != NULL)
6063 dns_request_cancel(zone->request);
6064 } else
6065 goto unlock;
6066
6067 /*
6068 * This needs to happen before clear_addresskeylist() sets
6069 * zone->masterscnt to 0:
6070 */
6071 if (zone->mastersok != NULL) {
6072 isc_mem_put(zone->mctx, zone->mastersok,
6073 zone->masterscnt * sizeof(bool));
6074 zone->mastersok = NULL;
6075 }
6076 clear_addresskeylist(&zone->masters, &zone->masterdscps,
6077 &zone->masterkeynames, &zone->masterscnt,
6078 zone->mctx);
6079 /*
6080 * If count == 0, don't allocate any space for masters, mastersok or
6081 * keynames so internally, those pointers are NULL if count == 0
6082 */
6083 if (count == 0)
6084 goto unlock;
6085
6086 /*
6087 * mastersok must contain count elements
6088 */
6089 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6090 if (newok == NULL) {
6091 result = ISC_R_NOMEMORY;
6092 isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
6093 goto unlock;
6094 };
6095 for (i = 0; i < count; i++)
6096 newok[i] = false;
6097
6098 /*
6099 * Now set up the masters and masterkey lists
6100 */
6101 result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
6102 keynames, &newnames, zone->mctx);
6103 INSIST(newdscps == NULL);
6104 if (result != ISC_R_SUCCESS) {
6105 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
6106 goto unlock;
6107 }
6108
6109 /*
6110 * Everything is ok so attach to the zone.
6111 */
6112 zone->curmaster = 0;
6113 zone->mastersok = newok;
6114 zone->masters = newaddrs;
6115 zone->masterdscps = newdscps;
6116 zone->masterkeynames = newnames;
6117 zone->masterscnt = count;
6118 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6119
6120 unlock:
6121 UNLOCK_ZONE(zone);
6122 return (result);
6123}
6124
6125isc_result_t
6126dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6127 isc_result_t result = ISC_R_SUCCESS;
6128
6129 REQUIRE(DNS_ZONE_VALID(zone));
6130
6131 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6132 if (zone->db == NULL)
6133 result = DNS_R_NOTLOADED;
6134 else
6135 dns_db_attach(zone->db, dpb);
6136 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6137
6138 return (result);
6139}
6140
6141void
6142dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6143 REQUIRE(DNS_ZONE_VALID(zone));
6144 REQUIRE(zone->type == dns_zone_staticstub);
6145
6146 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6147 REQUIRE(zone->db == NULL);
6148 dns_db_attach(db, &zone->db);
6149 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6150}
6151
6152/*
6153 * Co-ordinates the starting of routine jobs.
6154 */
6155void
6156dns_zone_maintenance(dns_zone_t *zone) {
6157 const char me[] = "dns_zone_maintenance";
6158 isc_time_t now;
6159
6160 REQUIRE(DNS_ZONE_VALID(zone));
6161 ENTER;
6162
6163 LOCK_ZONE(zone);
6164 TIME_NOW(&now);
6165 zone_settimer(zone, &now);
6166 UNLOCK_ZONE(zone);
6167}
6168
6169static inline bool
6170was_dumping(dns_zone_t *zone) {
6171 bool dumping;
6172
6173 REQUIRE(LOCKED_ZONE(zone));
6174
6175 dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
6176 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6177 if (!dumping) {
6178 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6179 isc_time_settoepoch(&zone->dumptime);
6180 }
6181 return (dumping);
6182}
6183
6184/*%
6185 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6186 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6187 * Only load the public part of a given key if it is not active at timestamp
6188 * 'now'. Store the number of keys found in 'nkeys'.
6189 */
6190isc_result_t
6191dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6192 isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6193 dst_key_t **keys, unsigned int *nkeys)
6194{
6195 isc_result_t result;
6196 dns_dbnode_t *node = NULL;
6197 const char *directory = dns_zone_getkeydirectory(zone);
6198
6199 CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6200 memset(keys, 0, sizeof(*keys) * maxkeys);
6201 result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6202 directory, now, mctx, maxkeys, keys,
6203 nkeys);
6204 if (result == ISC_R_NOTFOUND)
6205 result = ISC_R_SUCCESS;
6206 failure:
6207 if (node != NULL)
6208 dns_db_detachnode(db, &node);
6209 return (result);
6210}
6211
6212static isc_result_t
6213offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6214 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
6215{
6216 isc_result_t result;
6217
6218 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
6219 return (ISC_R_SUCCESS);
6220 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6221 name, ttl, rdata);
6222 if (result != ISC_R_SUCCESS)
6223 return (result);
6224 rdata->flags |= DNS_RDATA_OFFLINE;
6225 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6226 name, ttl, rdata);
6227 zonediff->offline = true;
6228 return (result);
6229}
6230
6231static void
6232set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
6233{
6234 unsigned int delta;
6235 char timebuf[80];
6236
6237 zone->key_expiry = when;
6238 if (when <= now) {
6239 dns_zone_log(zone, ISC_LOG_ERROR,
6240 "DNSKEY RRSIG(s) have expired");
6241 isc_time_settoepoch(&zone->keywarntime);
6242 } else if (when < now + 7 * 24 * 3600) {
6243 isc_time_t t;
6244 isc_time_set(&t, when, 0);
6245 isc_time_formattimestamp(&t, timebuf, 80);
6246 dns_zone_log(zone, ISC_LOG_WARNING,
6247 "DNSKEY RRSIG(s) will expire within 7 days: %s",
6248 timebuf);
6249 delta = when - now;
6250 delta--; /* loop prevention */
6251 delta /= 24 * 3600; /* to whole days */
6252 delta *= 24 * 3600; /* to seconds */
6253 isc_time_set(&zone->keywarntime, when - delta, 0);
6254 } else {
6255 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6256 isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6257 dns_zone_log(zone, ISC_LOG_NOTICE,
6258 "setting keywarntime to %s", timebuf);
6259 }
6260}
6261
6262/*
6263 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6264 * have no new key.
6265 */
6266static bool
6267delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6268 bool *warn)
6269{
6270 unsigned int i = 0;
6271 bool have_ksk = false, have_zsk = false;
6272 bool have_pksk = false, have_pzsk = false;
6273
6274 for (i = 0; i < nkeys; i++) {
6275 if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
6276 continue;
6277 if (dst_key_isprivate(keys[i])) {
6278 if (KSK(keys[i]))
6279 have_ksk = have_pksk = true;
6280 else
6281 have_zsk = have_pzsk = true;
6282 } else {
6283 if (KSK(keys[i]))
6284 have_ksk = true;
6285 else
6286 have_zsk = true;
6287 }
6288 }
6289
6290 if (have_zsk && have_ksk && !have_pzsk)
6291 *warn = true;
6292
6293 /*
6294 * It's okay to delete a signature if there is an active key
6295 * with the same algorithm to replace it.
6296 */
6297 if (have_pksk || have_pzsk)
6298 return (true);
6299
6300 /*
6301 * Failing that, it is *not* okay to delete a signature
6302 * if the associated public key is still in the DNSKEY RRset
6303 */
6304 for (i = 0; i < nkeys; i++) {
6305 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6306 (rrsig_ptr->keyid == dst_key_id(keys[i])))
6307 return (false);
6308 }
6309
6310 /*
6311 * But if the key is gone, then go ahead.
6312 */
6313 return (true);
6314}
6315
6316/*
6317 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6318 * See also update.c:del_keysigs().
6319 */
6320static isc_result_t
6321del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6322 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6323 unsigned int nkeys, isc_stdtime_t now, bool incremental)
6324{
6325 isc_result_t result;
6326 dns_dbnode_t *node = NULL;
6327 dns_rdataset_t rdataset;
6328 unsigned int i;
6329 dns_rdata_rrsig_t rrsig;
6330 bool found;
6331 int64_t timewarn = 0, timemaybe = 0;
6332
6333 dns_rdataset_init(&rdataset);
6334
6335 if (type == dns_rdatatype_nsec3)
6336 result = dns_db_findnsec3node(db, name, false, &node);
6337 else
6338 result = dns_db_findnode(db, name, false, &node);
6339 if (result == ISC_R_NOTFOUND)
6340 return (ISC_R_SUCCESS);
6341 if (result != ISC_R_SUCCESS)
6342 goto failure;
6343 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6344 (isc_stdtime_t) 0, &rdataset, NULL);
6345 dns_db_detachnode(db, &node);
6346
6347 if (result == ISC_R_NOTFOUND) {
6348 INSIST(!dns_rdataset_isassociated(&rdataset));
6349 return (ISC_R_SUCCESS);
6350 }
6351 if (result != ISC_R_SUCCESS) {
6352 INSIST(!dns_rdataset_isassociated(&rdataset));
6353 goto failure;
6354 }
6355
6356 for (result = dns_rdataset_first(&rdataset);
6357 result == ISC_R_SUCCESS;
6358 result = dns_rdataset_next(&rdataset)) {
6359 dns_rdata_t rdata = DNS_RDATA_INIT;
6360
6361 dns_rdataset_current(&rdataset, &rdata);
6362 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6363 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6364
6365 if (type != dns_rdatatype_dnskey) {
6366 bool warn = false, deleted = false;
6367 if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
6368 result = update_one_rr(db, ver, zonediff->diff,
6369 DNS_DIFFOP_DELRESIGN, name,
6370 rdataset.ttl, &rdata);
6371 if (result != ISC_R_SUCCESS)
6372 break;
6373 deleted = true;
6374 }
6375 if (warn) {
6376 /*
6377 * At this point, we've got an RRSIG,
6378 * which is signed by an inactive key.
6379 * An administrator needs to provide a new
6380 * key/alg, but until that time, we want to
6381 * keep the old RRSIG. Marking the key as
6382 * offline will prevent us spinning waiting
6383 * for the private part.
6384 */
6385 if (incremental && !deleted) {
6386 result = offline(db, ver, zonediff,
6387 name, rdataset.ttl,
6388 &rdata);
6389 if (result != ISC_R_SUCCESS)
6390 break;
6391 }
6392
6393 /*
6394 * Log the key id and algorithm of
6395 * the inactive key with no replacement
6396 */
6397 if (zone->log_key_expired_timer <= now) {
6398 char origin[DNS_NAME_FORMATSIZE];
6399 char algbuf[DNS_NAME_FORMATSIZE];
6400 dns_name_format(&zone->origin, origin,
6401 sizeof(origin));
6402 dns_secalg_format(rrsig.algorithm,
6403 algbuf,
6404 sizeof(algbuf));
6405 dns_zone_log(zone, ISC_LOG_WARNING,
6406 "Key %s/%s/%d "
6407 "missing or inactive "
6408 "and has no replacement: "
6409 "retaining signatures.",
6410 origin, algbuf,
6411 rrsig.keyid);
6412 zone->log_key_expired_timer = now +
6413 3600;
6414 }
6415 }
6416 continue;
6417 }
6418
6419 /*
6420 * RRSIG(DNSKEY) requires special processing.
6421 */
6422 found = false;
6423 for (i = 0; i < nkeys; i++) {
6424 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6425 rrsig.keyid == dst_key_id(keys[i])) {
6426 found = true;
6427 /*
6428 * Mark offline RRSIG(DNSKEY).
6429 * We want the earliest offline expire time
6430 * iff there is a new offline signature.
6431 */
6432 if (!dst_key_inactive(keys[i]) &&
6433 !dst_key_isprivate(keys[i]))
6434 {
6435 int64_t timeexpire =
6436 dns_time64_from32(rrsig.timeexpire);
6437 if (timewarn != 0 &&
6438 timewarn > timeexpire)
6439 timewarn = timeexpire;
6440 if (rdata.flags & DNS_RDATA_OFFLINE) {
6441 if (timemaybe == 0 ||
6442 timemaybe > timeexpire)
6443 timemaybe = timeexpire;
6444 break;
6445 }
6446 if (timewarn == 0)
6447 timewarn = timemaybe;
6448 if (timewarn == 0 ||
6449 timewarn > timeexpire)
6450 timewarn = timeexpire;
6451 result = offline(db, ver, zonediff,
6452 name, rdataset.ttl,
6453 &rdata);
6454 break;
6455 }
6456 result = update_one_rr(db, ver, zonediff->diff,
6457 DNS_DIFFOP_DELRESIGN,
6458 name, rdataset.ttl,
6459 &rdata);
6460 break;
6461 }
6462 }
6463
6464 /*
6465 * If there is not a matching DNSKEY then
6466 * delete the RRSIG.
6467 */
6468 if (!found)
6469 result = update_one_rr(db, ver, zonediff->diff,
6470 DNS_DIFFOP_DELRESIGN, name,
6471 rdataset.ttl, &rdata);
6472 if (result != ISC_R_SUCCESS)
6473 break;
6474 }
6475
6476 dns_rdataset_disassociate(&rdataset);
6477 if (result == ISC_R_NOMORE)
6478 result = ISC_R_SUCCESS;
6479 if (timewarn > 0) {
6480 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
6481 if (timewarn == stdwarn) {
6482 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
6483 now);
6484 } else {
6485 dns_zone_log(zone, ISC_LOG_ERROR,
6486 "key expiry warning time out of range");
6487 }
6488 }
6489 failure:
6490 if (node != NULL)
6491 dns_db_detachnode(db, &node);
6492 return (result);
6493}
6494
6495static isc_result_t
6496add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6497 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
6498 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
6499 isc_stdtime_t expire, bool check_ksk,
6500 bool keyset_kskonly)
6501{
6502 isc_result_t result;
6503 dns_dbnode_t *node = NULL;
6504 dns_rdataset_t rdataset;
6505 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
6506 unsigned char data[1024]; /* XXX */
6507 isc_buffer_t buffer;
6508 unsigned int i, j;
6509
6510 dns_rdataset_init(&rdataset);
6511 isc_buffer_init(&buffer, data, sizeof(data));
6512
6513 if (type == dns_rdatatype_nsec3)
6514 result = dns_db_findnsec3node(db, name, false, &node);
6515 else
6516 result = dns_db_findnode(db, name, false, &node);
6517 if (result == ISC_R_NOTFOUND)
6518 return (ISC_R_SUCCESS);
6519 if (result != ISC_R_SUCCESS)
6520 goto failure;
6521 result = dns_db_findrdataset(db, node, ver, type, 0,
6522 (isc_stdtime_t) 0, &rdataset, NULL);
6523 dns_db_detachnode(db, &node);
6524 if (result == ISC_R_NOTFOUND) {
6525 INSIST(!dns_rdataset_isassociated(&rdataset));
6526 return (ISC_R_SUCCESS);
6527 }
6528 if (result != ISC_R_SUCCESS) {
6529 INSIST(!dns_rdataset_isassociated(&rdataset));
6530 goto failure;
6531 }
6532
6533 for (i = 0; i < nkeys; i++) {
6534 bool both = false;
6535
6536 if (!dst_key_isprivate(keys[i]))
6537 continue;
6538 if (dst_key_inactive(keys[i])) /* Should be redundant. */
6539 continue;
6540
6541 if (check_ksk && !REVOKE(keys[i])) {
6542 bool have_ksk, have_nonksk;
6543 if (KSK(keys[i])) {
6544 have_ksk = true;
6545 have_nonksk = false;
6546 } else {
6547 have_ksk = false;
6548 have_nonksk = true;
6549 }
6550 for (j = 0; j < nkeys; j++) {
6551 if (j == i || ALG(keys[i]) != ALG(keys[j]))
6552 continue;
6553 if (!dst_key_isprivate(keys[j]))
6554 continue;
6555 if (dst_key_inactive(keys[j])) /* SBR */
6556 continue;
6557 if (REVOKE(keys[j]))
6558 continue;
6559 if (KSK(keys[j]))
6560 have_ksk = true;
6561 else
6562 have_nonksk = true;
6563 both = have_ksk && have_nonksk;
6564 if (both)
6565 break;
6566 }
6567 }
6568 if (both) {
6569 /*
6570 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
6571 */
6572 if (type == dns_rdatatype_dnskey ||
6573 type == dns_rdatatype_cdnskey ||
6574 type == dns_rdatatype_cds)
6575 {
6576 if (!KSK(keys[i]) && keyset_kskonly)
6577 continue;
6578 } else if (KSK(keys[i])) {
6579 continue;
6580 }
6581 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
6582 continue;
6583 }
6584
6585 /* Calculate the signature, creating a RRSIG RDATA. */
6586 isc_buffer_clear(&buffer);
6587 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
6588 &inception, &expire,
6589 mctx, &buffer, &sig_rdata));
6590 /* Update the database and journal with the RRSIG. */
6591 /* XXX inefficient - will cause dataset merging */
6592 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
6593 name, rdataset.ttl, &sig_rdata));
6594 dns_rdata_reset(&sig_rdata);
6595 isc_buffer_init(&buffer, data, sizeof(data));
6596 }
6597
6598 failure:
6599 if (dns_rdataset_isassociated(&rdataset))
6600 dns_rdataset_disassociate(&rdataset);
6601 if (node != NULL)
6602 dns_db_detachnode(db, &node);
6603 return (result);
6604}
6605
6606static void
6607zone_resigninc(dns_zone_t *zone) {
6608 const char *me = "zone_resigninc";
6609 dns_db_t *db = NULL;
6610 dns_dbversion_t *version = NULL;
6611 dns_diff_t _sig_diff;
6612 dns__zonediff_t zonediff;
6613 dns_fixedname_t fixed;
6614 dns_name_t *name;
6615 dns_rdataset_t rdataset;
6616 dns_rdatatype_t covers;
6617 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6618 bool check_ksk, keyset_kskonly = false;
6619 isc_result_t result;
6620 isc_stdtime_t now, inception, soaexpire, expire, stop;
6621 uint32_t jitter, sigvalidityinterval;
6622 unsigned int i;
6623 unsigned int nkeys = 0;
6624 unsigned int resign;
6625
6626 ENTER;
6627
6628 dns_rdataset_init(&rdataset);
6629 dns_diff_init(zone->mctx, &_sig_diff);
6630 zonediff_init(&zonediff, &_sig_diff);
6631
6632 /*
6633 * Zone is frozen or automatic resigning is disabled.
6634 * Pause for 5 minutes.
6635 */
6636 if (zone->update_disabled ||
6637 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
6638 {
6639 result = ISC_R_FAILURE;
6640 goto failure;
6641 }
6642
6643 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6644 dns_db_attach(zone->db, &db);
6645 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6646
6647 result = dns_db_newversion(db, &version);
6648 if (result != ISC_R_SUCCESS) {
6649 dns_zone_log(zone, ISC_LOG_ERROR,
6650 "zone_resigninc:dns_db_newversion -> %s",
6651 dns_result_totext(result));
6652 goto failure;
6653 }
6654
6655 isc_stdtime_get(&now);
6656
6657 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
6658 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6659 if (result != ISC_R_SUCCESS) {
6660 dns_zone_log(zone, ISC_LOG_ERROR,
6661 "zone_resigninc:dns__zone_findkeys -> %s",
6662 dns_result_totext(result));
6663 goto failure;
6664 }
6665
6666 sigvalidityinterval = zone->sigvalidityinterval;
6667 inception = now - 3600; /* Allow for clock skew. */
6668 soaexpire = now + sigvalidityinterval;
6669 /*
6670 * Spread out signatures over time if they happen to be
6671 * clumped. We don't do this for each add_sigs() call as
6672 * we still want some clustering to occur.
6673 */
6674 if (sigvalidityinterval >= 3600U) {
6675 if (sigvalidityinterval > 7200U) {
6676 jitter = isc_random_uniform(3600);
6677 } else {
6678 jitter = isc_random_uniform(1200);
6679 }
6680 expire = soaexpire - jitter - 1;
6681 } else {
6682 expire = soaexpire - 1;
6683 }
6684 stop = now + 5;
6685
6686 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6687 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6688
6689 name = dns_fixedname_initname(&fixed);
6690 result = dns_db_getsigningtime(db, &rdataset, name);
6691 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6692 dns_zone_log(zone, ISC_LOG_ERROR,
6693 "zone_resigninc:dns_db_getsigningtime -> %s",
6694 dns_result_totext(result));
6695 }
6696
6697 i = 0;
6698 while (result == ISC_R_SUCCESS) {
6699 resign = rdataset.resign - zone->sigresigninginterval;
6700 covers = rdataset.covers;
6701 dns_rdataset_disassociate(&rdataset);
6702
6703 /*
6704 * Stop if we hit the SOA as that means we have walked the
6705 * entire zone. The SOA record should always be the most
6706 * recent signature.
6707 */
6708 /* XXXMPA increase number of RRsets signed pre call */
6709 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
6710 resign > stop)
6711 break;
6712
6713 result = del_sigs(zone, db, version, name, covers, &zonediff,
6714 zone_keys, nkeys, now, true);
6715 if (result != ISC_R_SUCCESS) {
6716 dns_zone_log(zone, ISC_LOG_ERROR,
6717 "zone_resigninc:del_sigs -> %s",
6718 dns_result_totext(result));
6719 break;
6720 }
6721
6722 result = add_sigs(db, version, name, covers, zonediff.diff,
6723 zone_keys, nkeys, zone->mctx, inception,
6724 expire, check_ksk, keyset_kskonly);
6725 if (result != ISC_R_SUCCESS) {
6726 dns_zone_log(zone, ISC_LOG_ERROR,
6727 "zone_resigninc:add_sigs -> %s",
6728 dns_result_totext(result));
6729 break;
6730 }
6731 result = dns_db_getsigningtime(db, &rdataset, name);
6732 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
6733 result = ISC_R_SUCCESS;
6734 break;
6735 }
6736 if (result != ISC_R_SUCCESS)
6737 dns_zone_log(zone, ISC_LOG_ERROR,
6738 "zone_resigninc:dns_db_getsigningtime -> %s",
6739 dns_result_totext(result));
6740 }
6741
6742 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
6743 goto failure;
6744
6745 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6746 &zonediff, zone_keys, nkeys, now, true);
6747 if (result != ISC_R_SUCCESS) {
6748 dns_zone_log(zone, ISC_LOG_ERROR,
6749 "zone_resigninc:del_sigs -> %s",
6750 dns_result_totext(result));
6751 goto failure;
6752 }
6753
6754 /*
6755 * Did we change anything in the zone?
6756 */
6757 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
6758 /*
6759 * Commit the changes if any key has been marked as offline.
6760 */
6761 if (zonediff.offline)
6762 dns_db_closeversion(db, &version, true);
6763 goto failure;
6764 }
6765
6766 /* Increment SOA serial if we have made changes */
6767 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
6768 zone->updatemethod);
6769 if (result != ISC_R_SUCCESS) {
6770 dns_zone_log(zone, ISC_LOG_ERROR,
6771 "zone_resigninc:update_soa_serial -> %s",
6772 dns_result_totext(result));
6773 goto failure;
6774 }
6775
6776 /*
6777 * Generate maximum life time signatures so that the above loop
6778 * termination is sensible.
6779 */
6780 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6781 zonediff.diff, zone_keys, nkeys, zone->mctx,
6782 inception, soaexpire, check_ksk, keyset_kskonly);
6783 if (result != ISC_R_SUCCESS) {
6784 dns_zone_log(zone, ISC_LOG_ERROR,
6785 "zone_resigninc:add_sigs -> %s",
6786 dns_result_totext(result));
6787 goto failure;
6788 }
6789
6790 /* Write changes to journal file. */
6791 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
6792
6793 /* Everything has succeeded. Commit the changes. */
6794 dns_db_closeversion(db, &version, true);
6795
6796 failure:
6797 dns_diff_clear(&_sig_diff);
6798 for (i = 0; i < nkeys; i++)
6799 dst_key_free(&zone_keys[i]);
6800 if (version != NULL) {
6801 dns_db_closeversion(db, &version, false);
6802 dns_db_detach(&db);
6803 } else if (db != NULL)
6804 dns_db_detach(&db);
6805 if (result == ISC_R_SUCCESS) {
6806 set_resigntime(zone);
6807 LOCK_ZONE(zone);
6808 zone_needdump(zone, DNS_DUMP_DELAY);
6809 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6810 UNLOCK_ZONE(zone);
6811 } else {
6812 /*
6813 * Something failed. Retry in 5 minutes.
6814 */
6815 isc_interval_t ival;
6816 isc_interval_set(&ival, 300, 0);
6817 isc_time_nowplusinterval(&zone->resigntime, &ival);
6818 }
6819
6820 INSIST(version == NULL);
6821}
6822
6823static isc_result_t
6824next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
6825 dns_name_t *newname, bool bottom)
6826{
6827 isc_result_t result;
6828 dns_dbiterator_t *dbit = NULL;
6829 dns_rdatasetiter_t *rdsit = NULL;
6830 dns_dbnode_t *node = NULL;
6831
6832 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
6833 CHECK(dns_dbiterator_seek(dbit, oldname));
6834 do {
6835 result = dns_dbiterator_next(dbit);
6836 if (result == ISC_R_NOMORE)
6837 CHECK(dns_dbiterator_first(dbit));
6838 CHECK(dns_dbiterator_current(dbit, &node, newname));
6839 if (bottom && dns_name_issubdomain(newname, oldname) &&
6840 !dns_name_equal(newname, oldname)) {
6841 dns_db_detachnode(db, &node);
6842 continue;
6843 }
6844 /*
6845 * Is this node empty?
6846 */
6847 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
6848 result = dns_rdatasetiter_first(rdsit);
6849 dns_db_detachnode(db, &node);
6850 dns_rdatasetiter_destroy(&rdsit);
6851 if (result != ISC_R_NOMORE)
6852 break;
6853 } while (1);
6854 failure:
6855 if (node != NULL)
6856 dns_db_detachnode(db, &node);
6857 if (dbit != NULL)
6858 dns_dbiterator_destroy(&dbit);
6859 return (result);
6860}
6861
6862static bool
6863signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
6864 dns_rdatatype_t type, dst_key_t *key)
6865{
6866 isc_result_t result;
6867 dns_rdataset_t rdataset;
6868 dns_rdata_t rdata = DNS_RDATA_INIT;
6869 dns_rdata_rrsig_t rrsig;
6870
6871 dns_rdataset_init(&rdataset);
6872 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
6873 type, 0, &rdataset, NULL);
6874 if (result != ISC_R_SUCCESS) {
6875 INSIST(!dns_rdataset_isassociated(&rdataset));
6876 return (false);
6877 }
6878 for (result = dns_rdataset_first(&rdataset);
6879 result == ISC_R_SUCCESS;
6880 result = dns_rdataset_next(&rdataset)) {
6881 dns_rdataset_current(&rdataset, &rdata);
6882 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6883 INSIST(result == ISC_R_SUCCESS);
6884 if (rrsig.algorithm == dst_key_alg(key) &&
6885 rrsig.keyid == dst_key_id(key)) {
6886 dns_rdataset_disassociate(&rdataset);
6887 return (true);
6888 }
6889 dns_rdata_reset(&rdata);
6890 }
6891 dns_rdataset_disassociate(&rdataset);
6892 return (false);
6893}
6894
6895static isc_result_t
6896add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6897 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom,
6898 dns_diff_t *diff)
6899{
6900 dns_fixedname_t fixed;
6901 dns_name_t *next;
6902 dns_rdata_t rdata = DNS_RDATA_INIT;
6903 isc_result_t result;
6904 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
6905
6906 next = dns_fixedname_initname(&fixed);
6907
6908 CHECK(next_active(db, version, name, next, bottom));
6909 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
6910 &rdata));
6911 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
6912 &rdata));
6913 failure:
6914 return (result);
6915}
6916
6917static isc_result_t
6918check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
6919 dns_dbversion_t *version, bool *is_bottom_of_zone)
6920{
6921 isc_result_t result;
6922 dns_rdatasetiter_t *iterator = NULL;
6923 dns_rdataset_t rdataset;
6924 bool seen_soa = false, seen_ns = false, seen_dname = false;
6925
6926 REQUIRE(is_bottom_of_zone != NULL);
6927
6928 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6929 if (result != ISC_R_SUCCESS) {
6930 if (result == ISC_R_NOTFOUND) {
6931 result = ISC_R_SUCCESS;
6932 }
6933 return (result);
6934 }
6935
6936 dns_rdataset_init(&rdataset);
6937 for (result = dns_rdatasetiter_first(iterator);
6938 result == ISC_R_SUCCESS;
6939 result = dns_rdatasetiter_next(iterator)) {
6940 dns_rdatasetiter_current(iterator, &rdataset);
6941 switch (rdataset.type) {
6942 case dns_rdatatype_soa:
6943 seen_soa = true;
6944 break;
6945 case dns_rdatatype_ns:
6946 seen_ns = true;
6947 break;
6948 case dns_rdatatype_dname:
6949 seen_dname = true;
6950 break;
6951 }
6952 dns_rdataset_disassociate(&rdataset);
6953 }
6954 if (result != ISC_R_NOMORE) {
6955 goto failure;
6956 }
6957 if ((seen_ns && !seen_soa) || seen_dname) {
6958 *is_bottom_of_zone = true;
6959 }
6960 result = ISC_R_SUCCESS;
6961
6962 failure:
6963 dns_rdatasetiter_destroy(&iterator);
6964
6965 return (result);
6966}
6967
6968static isc_result_t
6969sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
6970 dns_dbversion_t *version, bool build_nsec3,
6971 bool build_nsec, dst_key_t *key,
6972 isc_stdtime_t inception, isc_stdtime_t expire,
6973 unsigned int minimum, bool is_ksk,
6974 bool keyset_kskonly, bool is_bottom_of_zone,
6975 dns_diff_t *diff, int32_t *signatures, isc_mem_t *mctx)
6976{
6977 isc_result_t result;
6978 dns_rdatasetiter_t *iterator = NULL;
6979 dns_rdataset_t rdataset;
6980 dns_rdata_t rdata = DNS_RDATA_INIT;
6981 isc_buffer_t buffer;
6982 unsigned char data[1024];
6983 bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
6984
6985 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6986 if (result != ISC_R_SUCCESS) {
6987 if (result == ISC_R_NOTFOUND)
6988 result = ISC_R_SUCCESS;
6989 return (result);
6990 }
6991
6992 dns_rdataset_init(&rdataset);
6993 isc_buffer_init(&buffer, data, sizeof(data));
6994 seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
6995 for (result = dns_rdatasetiter_first(iterator);
6996 result == ISC_R_SUCCESS;
6997 result = dns_rdatasetiter_next(iterator)) {
6998 dns_rdatasetiter_current(iterator, &rdataset);
6999 if (rdataset.type == dns_rdatatype_soa)
7000 seen_soa = true;
7001 else if (rdataset.type == dns_rdatatype_ns)
7002 seen_ns = true;
7003 else if (rdataset.type == dns_rdatatype_ds)
7004 seen_ds = true;
7005 else if (rdataset.type == dns_rdatatype_nsec)
7006 seen_nsec = true;
7007 else if (rdataset.type == dns_rdatatype_nsec3)
7008 seen_nsec3 = true;
7009 if (rdataset.type != dns_rdatatype_rrsig)
7010 seen_rr = true;
7011 dns_rdataset_disassociate(&rdataset);
7012 }
7013 if (result != ISC_R_NOMORE)
7014 goto failure;
7015 /*
7016 * Going from insecure to NSEC3.
7017 * Don't generate NSEC3 records for NSEC3 records.
7018 */
7019 if (build_nsec3 && !seen_nsec3 && seen_rr) {
7020 bool unsecure = !seen_ds && seen_ns && !seen_soa;
7021 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
7022 unsecure, diff));
7023 (*signatures)--;
7024 }
7025 /*
7026 * Going from insecure to NSEC.
7027 * Don't generate NSEC records for NSEC3 records.
7028 */
7029 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
7030 /*
7031 * Build a NSEC record except at the origin.
7032 */
7033 if (!dns_name_equal(name, dns_db_origin(db))) {
7034 CHECK(add_nsec(db, version, name, node, minimum,
7035 is_bottom_of_zone, diff));
7036 /* Count a NSEC generation as a signature generation. */
7037 (*signatures)--;
7038 }
7039 }
7040 result = dns_rdatasetiter_first(iterator);
7041 while (result == ISC_R_SUCCESS) {
7042 dns_rdatasetiter_current(iterator, &rdataset);
7043 if (rdataset.type == dns_rdatatype_soa ||
7044 rdataset.type == dns_rdatatype_rrsig)
7045 {
7046 goto next_rdataset;
7047 }
7048 if (rdataset.type == dns_rdatatype_dnskey ||
7049 rdataset.type == dns_rdatatype_cdnskey ||
7050 rdataset.type == dns_rdatatype_cds)
7051 {
7052 /*
7053 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7054 * (RFC 7344, section 4.1 specifies that they must
7055 * be signed with a key in the current DS RRset,
7056 * which would only include KSK's.)
7057 */
7058 if (!is_ksk && keyset_kskonly) {
7059 goto next_rdataset;
7060 }
7061 } else if (is_ksk) {
7062 goto next_rdataset;
7063 }
7064 if (seen_ns && !seen_soa &&
7065 rdataset.type != dns_rdatatype_ds &&
7066 rdataset.type != dns_rdatatype_nsec)
7067 {
7068 goto next_rdataset;
7069 }
7070 if (signed_with_key(db, node, version, rdataset.type, key)) {
7071 goto next_rdataset;
7072 }
7073 /* Calculate the signature, creating a RRSIG RDATA. */
7074 isc_buffer_clear(&buffer);
7075 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
7076 &expire, mctx, &buffer, &rdata));
7077 /* Update the database and journal with the RRSIG. */
7078 /* XXX inefficient - will cause dataset merging */
7079 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7080 name, rdataset.ttl, &rdata));
7081 dns_rdata_reset(&rdata);
7082 (*signatures)--;
7083 next_rdataset:
7084 dns_rdataset_disassociate(&rdataset);
7085 result = dns_rdatasetiter_next(iterator);
7086 }
7087 if (result == ISC_R_NOMORE)
7088 result = ISC_R_SUCCESS;
7089 failure:
7090 if (dns_rdataset_isassociated(&rdataset))
7091 dns_rdataset_disassociate(&rdataset);
7092 if (iterator != NULL)
7093 dns_rdatasetiter_destroy(&iterator);
7094 return (result);
7095}
7096
7097/*
7098 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7099 */
7100static isc_result_t
7101updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7102 dns_ttl_t minimum, bool update_only, dns_diff_t *diff)
7103{
7104 isc_result_t result;
7105 dns_rdataset_t rdataset;
7106 dns_dbnode_t *node = NULL;
7107
7108 CHECK(dns_db_getoriginnode(db, &node));
7109 if (update_only) {
7110 dns_rdataset_init(&rdataset);
7111 result = dns_db_findrdataset(db, node, version,
7112 dns_rdatatype_nsec,
7113 dns_rdatatype_none,
7114 0, &rdataset, NULL);
7115 if (dns_rdataset_isassociated(&rdataset))
7116 dns_rdataset_disassociate(&rdataset);
7117 if (result == ISC_R_NOTFOUND)
7118 goto success;
7119 if (result != ISC_R_SUCCESS)
7120 goto failure;
7121 }
7122 CHECK(delete_nsec(db, version, node, name, diff));
7123 CHECK(add_nsec(db, version, name, node, minimum, false, diff));
7124 success:
7125 result = ISC_R_SUCCESS;
7126 failure:
7127 if (node != NULL)
7128 dns_db_detachnode(db, &node);
7129 return (result);
7130}
7131
7132static isc_result_t
7133updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7134 dns_dbversion_t *version, bool build_nsec3,
7135 dns_ttl_t minimum, dns_diff_t *diff)
7136{
7137 isc_result_t result;
7138 dns_dbnode_t *node = NULL;
7139 dns_rdataset_t rdataset;
7140 dns_rdata_t rdata = DNS_RDATA_INIT;
7141 unsigned char data[5];
7142 bool seen_done = false;
7143 bool have_rr = false;
7144
7145 dns_rdataset_init(&rdataset);
7146 result = dns_db_getoriginnode(signing->db, &node);
7147 if (result != ISC_R_SUCCESS)
7148 goto failure;
7149
7150 result = dns_db_findrdataset(signing->db, node, version,
7151 zone->privatetype, dns_rdatatype_none,
7152 0, &rdataset, NULL);
7153 if (result == ISC_R_NOTFOUND) {
7154 INSIST(!dns_rdataset_isassociated(&rdataset));
7155 result = ISC_R_SUCCESS;
7156 goto failure;
7157 }
7158 if (result != ISC_R_SUCCESS) {
7159 INSIST(!dns_rdataset_isassociated(&rdataset));
7160 goto failure;
7161 }
7162 for (result = dns_rdataset_first(&rdataset);
7163 result == ISC_R_SUCCESS;
7164 result = dns_rdataset_next(&rdataset)) {
7165 dns_rdataset_current(&rdataset, &rdata);
7166 /*
7167 * If we don't match the algorithm or keyid skip the record.
7168 */
7169 if (rdata.length != 5 ||
7170 rdata.data[0] != signing->algorithm ||
7171 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7172 rdata.data[2] != (signing->keyid & 0xff)) {
7173 have_rr = true;
7174 dns_rdata_reset(&rdata);
7175 continue;
7176 }
7177 /*
7178 * We have a match. If we were signing (!signing->deleteit)
7179 * and we already have a record indicating that we have
7180 * finished signing (rdata.data[4] != 0) then keep it.
7181 * Otherwise it needs to be deleted as we have removed all
7182 * the signatures (signing->deleteit), so any record indicating
7183 * completion is now out of date, or we have finished signing
7184 * with the new record so we no longer need to remember that
7185 * we need to sign the zone with the matching key across a
7186 * nameserver re-start.
7187 */
7188 if (!signing->deleteit && rdata.data[4] != 0) {
7189 seen_done = true;
7190 have_rr = true;
7191 } else
7192 CHECK(update_one_rr(signing->db, version, diff,
7193 DNS_DIFFOP_DEL, &zone->origin,
7194 rdataset.ttl, &rdata));
7195 dns_rdata_reset(&rdata);
7196 }
7197 if (result == ISC_R_NOMORE)
7198 result = ISC_R_SUCCESS;
7199 if (!signing->deleteit && !seen_done) {
7200 /*
7201 * If we were signing then we need to indicate that we have
7202 * finished signing the zone with this key. If it is already
7203 * there we don't need to add it a second time.
7204 */
7205 data[0] = signing->algorithm;
7206 data[1] = (signing->keyid >> 8) & 0xff;
7207 data[2] = signing->keyid & 0xff;
7208 data[3] = 0;
7209 data[4] = 1;
7210 rdata.length = sizeof(data);
7211 rdata.data = data;
7212 rdata.type = zone->privatetype;
7213 rdata.rdclass = dns_db_class(signing->db);
7214 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
7215 &zone->origin, rdataset.ttl, &rdata));
7216 } else if (!have_rr) {
7217 dns_name_t *origin = dns_db_origin(signing->db);
7218 /*
7219 * Rebuild the NSEC/NSEC3 record for the origin as we no
7220 * longer have any private records.
7221 */
7222 if (build_nsec3)
7223 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
7224 minimum, false, diff));
7225 CHECK(updatesecure(signing->db, version, origin, minimum,
7226 true, diff));
7227 }
7228
7229 failure:
7230 if (dns_rdataset_isassociated(&rdataset))
7231 dns_rdataset_disassociate(&rdataset);
7232 if (node != NULL)
7233 dns_db_detachnode(signing->db, &node);
7234 return (result);
7235}
7236
7237/*
7238 * Called from zone_nsec3chain() in order to update zone records indicating
7239 * processing status of given NSEC3 chain:
7240 *
7241 * - If the supplied dns_nsec3chain_t structure has been fully processed
7242 * (which is indicated by "active" being set to false):
7243 *
7244 * - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
7245 *
7246 * - remove all private-type records containing NSEC3PARAM RDATA matching
7247 * the relevant NSEC3 chain.
7248 *
7249 * - If the supplied dns_nsec3chain_t structure has not been fully processed
7250 * (which is indicated by "active" being set to true), only remove the
7251 * NSEC3PARAM record which matches the relevant NSEC3 chain and has the
7252 * "flags" field set to 0.
7253 *
7254 * - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
7255 * in the relevant private-type record, but with the "flags" field set to
7256 * 0, indicating that this NSEC3 chain is now complete for this zone.
7257 *
7258 * Note that this function is called at different processing stages for NSEC3
7259 * chain additions vs. removals and needs to handle all cases properly.
7260 */
7261static isc_result_t
7262fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
7263 bool active, dns_rdatatype_t privatetype,
7264 dns_diff_t *diff)
7265{
7266 dns_dbnode_t *node = NULL;
7267 dns_name_t *name = dns_db_origin(db);
7268 dns_rdata_t rdata = DNS_RDATA_INIT;
7269 dns_rdataset_t rdataset;
7270 dns_rdata_nsec3param_t nsec3param;
7271 isc_result_t result;
7272 isc_buffer_t buffer;
7273 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
7274 dns_ttl_t ttl = 0;
7275 bool nseconly = false, nsec3ok = false;
7276
7277 dns_rdataset_init(&rdataset);
7278
7279 result = dns_db_getoriginnode(db, &node);
7280 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7281 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
7282 0, 0, &rdataset, NULL);
7283 if (result == ISC_R_NOTFOUND)
7284 goto try_private;
7285 if (result != ISC_R_SUCCESS)
7286 goto failure;
7287
7288 /*
7289 * Preserve the existing ttl.
7290 */
7291 ttl = rdataset.ttl;
7292
7293 /*
7294 * Delete all NSEC3PARAM records which match that in nsec3chain.
7295 */
7296 for (result = dns_rdataset_first(&rdataset);
7297 result == ISC_R_SUCCESS;
7298 result = dns_rdataset_next(&rdataset)) {
7299
7300 dns_rdataset_current(&rdataset, &rdata);
7301 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7302
7303 if (nsec3param.hash != chain->nsec3param.hash ||
7304 (active && nsec3param.flags != 0) ||
7305 nsec3param.iterations != chain->nsec3param.iterations ||
7306 nsec3param.salt_length != chain->nsec3param.salt_length ||
7307 memcmp(nsec3param.salt, chain->nsec3param.salt,
7308 nsec3param.salt_length)) {
7309 dns_rdata_reset(&rdata);
7310 continue;
7311 }
7312
7313 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
7314 name, rdataset.ttl, &rdata));
7315 dns_rdata_reset(&rdata);
7316 }
7317 if (result != ISC_R_NOMORE)
7318 goto failure;
7319
7320 dns_rdataset_disassociate(&rdataset);
7321
7322 try_private:
7323
7324 if (active)
7325 goto add;
7326
7327 result = dns_nsec_nseconly(db, ver, &nseconly);
7328 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
7329
7330 /*
7331 * Delete all private records which match that in nsec3chain.
7332 */
7333 result = dns_db_findrdataset(db, node, ver, privatetype,
7334 0, 0, &rdataset, NULL);
7335 if (result == ISC_R_NOTFOUND)
7336 goto add;
7337 if (result != ISC_R_SUCCESS)
7338 goto failure;
7339
7340 for (result = dns_rdataset_first(&rdataset);
7341 result == ISC_R_SUCCESS;
7342 result = dns_rdataset_next(&rdataset)) {
7343 dns_rdata_t private = DNS_RDATA_INIT;
7344 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
7345
7346 dns_rdataset_current(&rdataset, &private);
7347 if (!dns_nsec3param_fromprivate(&private, &rdata,
7348 buf, sizeof(buf)))
7349 continue;
7350 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7351
7352 if ((!nsec3ok &&
7353 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
7354 nsec3param.hash != chain->nsec3param.hash ||
7355 nsec3param.iterations != chain->nsec3param.iterations ||
7356 nsec3param.salt_length != chain->nsec3param.salt_length ||
7357 memcmp(nsec3param.salt, chain->nsec3param.salt,
7358 nsec3param.salt_length)) {
7359 dns_rdata_reset(&rdata);
7360 continue;
7361 }
7362
7363 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
7364 name, rdataset.ttl, &private));
7365 dns_rdata_reset(&rdata);
7366 }
7367 if (result != ISC_R_NOMORE)
7368 goto failure;
7369
7370 add:
7371 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
7372 result = ISC_R_SUCCESS;
7373 goto failure;
7374 }
7375
7376 /*
7377 * Add a NSEC3PARAM record which matches that in nsec3chain but
7378 * with all flags bits cleared.
7379 *
7380 * Note: we do not clear chain->nsec3param.flags as this change
7381 * may be reversed.
7382 */
7383 isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
7384 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
7385 dns_rdatatype_nsec3param,
7386 &chain->nsec3param, &buffer));
7387 rdata.data[1] = 0; /* Clear flag bits. */
7388 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
7389
7390 failure:
7391 dns_db_detachnode(db, &node);
7392 if (dns_rdataset_isassociated(&rdataset))
7393 dns_rdataset_disassociate(&rdataset);
7394 return (result);
7395}
7396
7397static isc_result_t
7398delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7399 dns_name_t *name, dns_diff_t *diff)
7400{
7401 dns_rdataset_t rdataset;
7402 isc_result_t result;
7403
7404 dns_rdataset_init(&rdataset);
7405
7406 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
7407 0, 0, &rdataset, NULL);
7408 if (result == ISC_R_NOTFOUND)
7409 return (ISC_R_SUCCESS);
7410 if (result != ISC_R_SUCCESS)
7411 return (result);
7412 for (result = dns_rdataset_first(&rdataset);
7413 result == ISC_R_SUCCESS;
7414 result = dns_rdataset_next(&rdataset)) {
7415 dns_rdata_t rdata = DNS_RDATA_INIT;
7416
7417 dns_rdataset_current(&rdataset, &rdata);
7418 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7419 rdataset.ttl, &rdata));
7420 }
7421 if (result == ISC_R_NOMORE)
7422 result = ISC_R_SUCCESS;
7423 failure:
7424 dns_rdataset_disassociate(&rdataset);
7425 return (result);
7426}
7427
7428static isc_result_t
7429deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7430 dns_name_t *name, const dns_rdata_nsec3param_t *param,
7431 dns_diff_t *diff)
7432{
7433 dns_rdataset_t rdataset;
7434 dns_rdata_nsec3_t nsec3;
7435 isc_result_t result;
7436
7437 dns_rdataset_init(&rdataset);
7438 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
7439 0, 0, &rdataset, NULL);
7440 if (result == ISC_R_NOTFOUND)
7441 return (ISC_R_SUCCESS);
7442 if (result != ISC_R_SUCCESS)
7443 return (result);
7444
7445 for (result = dns_rdataset_first(&rdataset);
7446 result == ISC_R_SUCCESS;
7447 result = dns_rdataset_next(&rdataset)) {
7448 dns_rdata_t rdata = DNS_RDATA_INIT;
7449
7450 dns_rdataset_current(&rdataset, &rdata);
7451 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
7452 if (nsec3.hash != param->hash ||
7453 nsec3.iterations != param->iterations ||
7454 nsec3.salt_length != param->salt_length ||
7455 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
7456 continue;
7457 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7458 rdataset.ttl, &rdata));
7459 }
7460 if (result == ISC_R_NOMORE)
7461 result = ISC_R_SUCCESS;
7462 failure:
7463 dns_rdataset_disassociate(&rdataset);
7464 return (result);
7465}
7466
7467static isc_result_t
7468need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
7469 const dns_rdata_nsec3param_t *param,
7470 bool *answer)
7471{
7472 dns_dbnode_t *node = NULL;
7473 dns_rdata_t rdata = DNS_RDATA_INIT;
7474 dns_rdata_nsec3param_t myparam;
7475 dns_rdataset_t rdataset;
7476 isc_result_t result;
7477
7478 *answer = false;
7479
7480 result = dns_db_getoriginnode(db, &node);
7481 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7482
7483 dns_rdataset_init(&rdataset);
7484
7485 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
7486 0, 0, &rdataset, NULL);
7487 if (result == ISC_R_SUCCESS) {
7488 dns_rdataset_disassociate(&rdataset);
7489 dns_db_detachnode(db, &node);
7490 return (result);
7491 }
7492 if (result != ISC_R_NOTFOUND) {
7493 dns_db_detachnode(db, &node);
7494 return (result);
7495 }
7496
7497 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
7498 0, 0, &rdataset, NULL);
7499 if (result == ISC_R_NOTFOUND) {
7500 *answer = true;
7501 dns_db_detachnode(db, &node);
7502 return (ISC_R_SUCCESS);
7503 }
7504 if (result != ISC_R_SUCCESS) {
7505 dns_db_detachnode(db, &node);
7506 return (result);
7507 }
7508
7509 for (result = dns_rdataset_first(&rdataset);
7510 result == ISC_R_SUCCESS;
7511 result = dns_rdataset_next(&rdataset)) {
7512 dns_rdataset_current(&rdataset, &rdata);
7513 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
7514 dns_rdata_reset(&rdata);
7515 /*
7516 * Ignore any NSEC3PARAM removals.
7517 */
7518 if (NSEC3REMOVE(myparam.flags))
7519 continue;
7520 /*
7521 * Ignore the chain that we are in the process of deleting.
7522 */
7523 if (myparam.hash == param->hash &&
7524 myparam.iterations == param->iterations &&
7525 myparam.salt_length == param->salt_length &&
7526 !memcmp(myparam.salt, param->salt, myparam.salt_length))
7527 continue;
7528 /*
7529 * Found an active NSEC3 chain.
7530 */
7531 break;
7532 }
7533 if (result == ISC_R_NOMORE) {
7534 *answer = true;
7535 result = ISC_R_SUCCESS;
7536 }
7537
7538 failure:
7539 if (dns_rdataset_isassociated(&rdataset))
7540 dns_rdataset_disassociate(&rdataset);
7541 dns_db_detachnode(db, &node);
7542 return (result);
7543}
7544
7545/*%
7546 * Given a tuple which is part of a diff, return a pointer to the next tuple in
7547 * that diff which has the same name and type (or NULL if no such tuple is
7548 * found).
7549 */
7550static dns_difftuple_t *
7551find_next_matching_tuple(dns_difftuple_t *cur) {
7552 dns_difftuple_t *next = cur;
7553
7554 while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
7555 if (cur->rdata.type == next->rdata.type &&
7556 dns_name_equal(&cur->name, &next->name))
7557 {
7558 return (next);
7559 }
7560 }
7561
7562 return (NULL);
7563}
7564
7565/*%
7566 * Remove all tuples with the same name and type as 'cur' from 'src' and append
7567 * them to 'dst'.
7568 */
7569static void
7570move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
7571 do {
7572 dns_difftuple_t *next = find_next_matching_tuple(cur);
7573 ISC_LIST_UNLINK(src->tuples, cur, link);
7574 dns_diff_appendminimal(dst, &cur);
7575 cur = next;
7576 } while (cur != NULL);
7577}
7578
7579/*%
7580 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
7581 * 'diff'. Gradually remove tuples from 'diff' and append them to 'zonediff'
7582 * along with tuples representing relevant signature changes.
7583 */
7584isc_result_t
7585dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
7586 dst_key_t *zone_keys[], unsigned int nkeys,
7587 dns_zone_t *zone, isc_stdtime_t inception,
7588 isc_stdtime_t expire, isc_stdtime_t keyexpire,
7589 isc_stdtime_t now, bool check_ksk,
7590 bool keyset_kskonly, dns__zonediff_t *zonediff)
7591{
7592 dns_difftuple_t *tuple;
7593 isc_result_t result;
7594
7595 while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
7596 isc_stdtime_t exp = expire;
7597
7598 if (keyexpire != 0 &&
7599 (tuple->rdata.type == dns_rdatatype_dnskey ||
7600 tuple->rdata.type == dns_rdatatype_cdnskey ||
7601 tuple->rdata.type == dns_rdatatype_cds))
7602 {
7603 exp = keyexpire;
7604 }
7605
7606 result = del_sigs(zone, db, version, &tuple->name,
7607 tuple->rdata.type, zonediff,
7608 zone_keys, nkeys, now, false);
7609 if (result != ISC_R_SUCCESS) {
7610 dns_zone_log(zone, ISC_LOG_ERROR,
7611 "dns__zone_updatesigs:del_sigs -> %s",
7612 dns_result_totext(result));
7613 return (result);
7614 }
7615 result = add_sigs(db, version, &tuple->name,
7616 tuple->rdata.type, zonediff->diff,
7617 zone_keys, nkeys, zone->mctx, inception,
7618 exp, check_ksk, keyset_kskonly);
7619 if (result != ISC_R_SUCCESS) {
7620 dns_zone_log(zone, ISC_LOG_ERROR,
7621 "dns__zone_updatesigs:add_sigs -> %s",
7622 dns_result_totext(result));
7623 return (result);
7624 }
7625
7626 /*
7627 * Signature changes for all RRs with name tuple->name and type
7628 * tuple->rdata.type were appended to zonediff->diff. Now we
7629 * remove all the "raw" changes with the same name and type
7630 * from diff (so that they are not processed by this loop
7631 * again) and append them to zonediff so that they get applied.
7632 */
7633 move_matching_tuples(tuple, diff, zonediff->diff);
7634 }
7635 return (ISC_R_SUCCESS);
7636}
7637
7638/*
7639 * Incrementally build and sign a new NSEC3 chain using the parameters
7640 * requested.
7641 */
7642static void
7643zone_nsec3chain(dns_zone_t *zone) {
7644 const char *me = "zone_nsec3chain";
7645 dns_db_t *db = NULL;
7646 dns_dbnode_t *node = NULL;
7647 dns_dbversion_t *version = NULL;
7648 dns_diff_t _sig_diff;
7649 dns_diff_t nsec_diff;
7650 dns_diff_t nsec3_diff;
7651 dns_diff_t param_diff;
7652 dns__zonediff_t zonediff;
7653 dns_fixedname_t fixed;
7654 dns_fixedname_t nextfixed;
7655 dns_name_t *name, *nextname;
7656 dns_rdataset_t rdataset;
7657 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
7658 dns_nsec3chainlist_t cleanup;
7659 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7660 int32_t signatures;
7661 bool check_ksk, keyset_kskonly;
7662 bool delegation;
7663 bool first;
7664 isc_result_t result;
7665 isc_stdtime_t now, inception, soaexpire, expire;
7666 uint32_t jitter, sigvalidityinterval;
7667 unsigned int i;
7668 unsigned int nkeys = 0;
7669 uint32_t nodes;
7670 bool unsecure = false;
7671 bool seen_soa, seen_ns, seen_dname, seen_ds;
7672 bool seen_nsec, seen_nsec3, seen_rr;
7673 dns_rdatasetiter_t *iterator = NULL;
7674 bool buildnsecchain;
7675 bool updatensec = false;
7676 dns_rdatatype_t privatetype = zone->privatetype;
7677
7678 ENTER;
7679
7680 dns_rdataset_init(&rdataset);
7681 name = dns_fixedname_initname(&fixed);
7682 nextname = dns_fixedname_initname(&nextfixed);
7683 dns_diff_init(zone->mctx, &param_diff);
7684 dns_diff_init(zone->mctx, &nsec3_diff);
7685 dns_diff_init(zone->mctx, &nsec_diff);
7686 dns_diff_init(zone->mctx, &_sig_diff);
7687 zonediff_init(&zonediff, &_sig_diff);
7688 ISC_LIST_INIT(cleanup);
7689
7690 /*
7691 * Updates are disabled. Pause for 5 minutes.
7692 */
7693 if (zone->update_disabled) {
7694 result = ISC_R_FAILURE;
7695 goto failure;
7696 }
7697
7698 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7699 /*
7700 * This function is called when zone timer fires, after the latter gets
7701 * set by zone_addnsec3chain(). If the action triggering the call to
7702 * zone_addnsec3chain() is closely followed by a zone deletion request,
7703 * it might turn out that the timer thread will not be woken up until
7704 * after the zone is deleted by rmzone(), which calls dns_db_detach()
7705 * for zone->db, causing the latter to become NULL. Return immediately
7706 * if that happens.
7707 */
7708 if (zone->db != NULL) {
7709 dns_db_attach(zone->db, &db);
7710 }
7711 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7712 if (db == NULL) {
7713 return;
7714 }
7715
7716 result = dns_db_newversion(db, &version);
7717 if (result != ISC_R_SUCCESS) {
7718 dnssec_log(zone, ISC_LOG_ERROR,
7719 "zone_nsec3chain:dns_db_newversion -> %s",
7720 dns_result_totext(result));
7721 goto failure;
7722 }
7723
7724 isc_stdtime_get(&now);
7725
7726 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7727 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7728 if (result != ISC_R_SUCCESS) {
7729 dnssec_log(zone, ISC_LOG_ERROR,
7730 "zone_nsec3chain:dns__zone_findkeys -> %s",
7731 dns_result_totext(result));
7732 goto failure;
7733 }
7734
7735 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7736 inception = now - 3600; /* Allow for clock skew. */
7737 soaexpire = now + sigvalidityinterval;
7738
7739 /*
7740 * Spread out signatures over time if they happen to be
7741 * clumped. We don't do this for each add_sigs() call as
7742 * we still want some clustering to occur.
7743 */
7744 if (sigvalidityinterval >= 3600U) {
7745 if (sigvalidityinterval > 7200U) {
7746 jitter = isc_random_uniform(3600);
7747 } else {
7748 jitter = isc_random_uniform(1200);
7749 }
7750 expire = soaexpire - jitter - 1;
7751 } else {
7752 expire = soaexpire - 1;
7753 }
7754
7755 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7756 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7757
7758 /*
7759 * We keep pulling nodes off each iterator in turn until
7760 * we have no more nodes to pull off or we reach the limits
7761 * for this quantum.
7762 */
7763 nodes = zone->nodes;
7764 signatures = zone->signatures;
7765 LOCK_ZONE(zone);
7766 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7767 UNLOCK_ZONE(zone);
7768 first = true;
7769
7770 if (nsec3chain != NULL) {
7771 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
7772 }
7773 /*
7774 * Generate new NSEC3 chains first.
7775 *
7776 * The following while loop iterates over nodes in the zone database,
7777 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
7778 * them. Once all nodes are processed, the "delete_nsec" field is
7779 * consulted to check whether we are supposed to remove NSEC records
7780 * from the zone database; if so, the database iterator is reset to
7781 * point to the first node and the loop traverses all of them again,
7782 * this time removing NSEC records. If we hit a node which is obscured
7783 * by a delegation or a DNAME, nodes are skipped over until we find one
7784 * that is not obscured by the same obscuring name and then normal
7785 * processing is resumed.
7786 *
7787 * The above is repeated until all requested NSEC3 chain changes are
7788 * applied or when we reach the limits for this quantum, whichever
7789 * happens first.
7790 *
7791 * Note that the "signatures" variable is only used here to limit the
7792 * amount of work performed. Actual DNSSEC signatures are only
7793 * generated by dns__zone_updatesigs() calls later in this function.
7794 */
7795 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
7796 LOCK_ZONE(zone);
7797 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
7798
7799 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7800 if (nsec3chain->done || nsec3chain->db != zone->db) {
7801 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
7802 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7803 }
7804 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7805 UNLOCK_ZONE(zone);
7806 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
7807 goto next_addchain;
7808
7809 /*
7810 * Possible future db.
7811 */
7812 if (nsec3chain->db != db) {
7813 goto next_addchain;
7814 }
7815
7816 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
7817 goto next_addchain;
7818
7819 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
7820
7821 if (nsec3chain->delete_nsec) {
7822 delegation = false;
7823 dns_dbiterator_pause(nsec3chain->dbiterator);
7824 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
7825 goto next_addnode;
7826 }
7827 /*
7828 * On the first pass we need to check if the current node
7829 * has not been obscured.
7830 */
7831 delegation = false;
7832 unsecure = false;
7833 if (first) {
7834 dns_fixedname_t ffound;
7835 dns_name_t *found;
7836 found = dns_fixedname_initname(&ffound);
7837 result = dns_db_find(db, name, version,
7838 dns_rdatatype_soa,
7839 DNS_DBFIND_NOWILD, 0, NULL, found,
7840 NULL, NULL);
7841 if ((result == DNS_R_DELEGATION ||
7842 result == DNS_R_DNAME) &&
7843 !dns_name_equal(name, found)) {
7844 /*
7845 * Remember the obscuring name so that
7846 * we skip all obscured names.
7847 */
7848 dns_name_copy(found, name, NULL);
7849 delegation = true;
7850 goto next_addnode;
7851 }
7852 }
7853
7854 /*
7855 * Check to see if this is a bottom of zone node.
7856 */
7857 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7858 if (result == ISC_R_NOTFOUND) {
7859 /* Empty node? */
7860 goto next_addnode;
7861 }
7862 if (result != ISC_R_SUCCESS) {
7863 goto failure;
7864 }
7865
7866 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
7867 for (result = dns_rdatasetiter_first(iterator);
7868 result == ISC_R_SUCCESS;
7869 result = dns_rdatasetiter_next(iterator))
7870 {
7871 dns_rdatasetiter_current(iterator, &rdataset);
7872 INSIST(rdataset.type != dns_rdatatype_nsec3);
7873 if (rdataset.type == dns_rdatatype_soa) {
7874 seen_soa = true;
7875 } else if (rdataset.type == dns_rdatatype_ns) {
7876 seen_ns = true;
7877 } else if (rdataset.type == dns_rdatatype_dname) {
7878 seen_dname = true;
7879 } else if (rdataset.type == dns_rdatatype_ds) {
7880 seen_ds = true;
7881 } else if (rdataset.type == dns_rdatatype_nsec) {
7882 seen_nsec = true;
7883 }
7884 dns_rdataset_disassociate(&rdataset);
7885 }
7886 dns_rdatasetiter_destroy(&iterator);
7887 /*
7888 * Is there a NSEC chain than needs to be cleaned up?
7889 */
7890 if (seen_nsec) {
7891 nsec3chain->seen_nsec = true;
7892 }
7893 if (seen_ns && !seen_soa && !seen_ds) {
7894 unsecure = true;
7895 }
7896 if ((seen_ns && !seen_soa) || seen_dname) {
7897 delegation = true;
7898 }
7899
7900 /*
7901 * Process one node.
7902 */
7903 dns_dbiterator_pause(nsec3chain->dbiterator);
7904 result = dns_nsec3_addnsec3(db, version, name,
7905 &nsec3chain->nsec3param,
7906 zone->minimum, unsecure,
7907 &nsec3_diff);
7908 if (result != ISC_R_SUCCESS) {
7909 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7910 "dns_nsec3_addnsec3 -> %s",
7911 dns_result_totext(result));
7912 goto failure;
7913 }
7914
7915 /*
7916 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
7917 * two signatures. Additionally there will, in general, be
7918 * two signature generated below.
7919 *
7920 * If we are only changing the optout flag the cost is half
7921 * that of the cost of generating a completely new chain.
7922 */
7923 signatures -= 4;
7924
7925 /*
7926 * Go onto next node.
7927 */
7928 next_addnode:
7929 first = false;
7930 dns_db_detachnode(db, &node);
7931 do {
7932 result = dns_dbiterator_next(nsec3chain->dbiterator);
7933
7934 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
7935 dns_dbiterator_pause(nsec3chain->dbiterator);
7936 CHECK(fixup_nsec3param(db, version, nsec3chain,
7937 false, privatetype,
7938 &param_diff));
7939 LOCK_ZONE(zone);
7940 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7941 link);
7942 UNLOCK_ZONE(zone);
7943 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7944 goto next_addchain;
7945 }
7946 if (result == ISC_R_NOMORE) {
7947 dns_dbiterator_pause(nsec3chain->dbiterator);
7948 if (nsec3chain->seen_nsec) {
7949 CHECK(fixup_nsec3param(db, version,
7950 nsec3chain,
7951 true,
7952 privatetype,
7953 &param_diff));
7954 nsec3chain->delete_nsec = true;
7955 goto same_addchain;
7956 }
7957 CHECK(fixup_nsec3param(db, version, nsec3chain,
7958 false, privatetype,
7959 &param_diff));
7960 LOCK_ZONE(zone);
7961 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7962 link);
7963 UNLOCK_ZONE(zone);
7964 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7965 goto next_addchain;
7966 } else if (result != ISC_R_SUCCESS) {
7967 dnssec_log(zone, ISC_LOG_ERROR,
7968 "zone_nsec3chain:"
7969 "dns_dbiterator_next -> %s",
7970 dns_result_totext(result));
7971 goto failure;
7972 } else if (delegation) {
7973 dns_dbiterator_current(nsec3chain->dbiterator,
7974 &node, nextname);
7975 dns_db_detachnode(db, &node);
7976 if (!dns_name_issubdomain(nextname, name))
7977 break;
7978 } else {
7979 break;
7980 }
7981 } while (1);
7982 continue;
7983
7984 same_addchain:
7985 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7986 first = true;
7987 continue;
7988
7989 next_addchain:
7990 dns_dbiterator_pause(nsec3chain->dbiterator);
7991 nsec3chain = nextnsec3chain;
7992 first = true;
7993 if (nsec3chain != NULL) {
7994 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
7995 }
7996 }
7997
7998 if (nsec3chain != NULL) {
7999 goto skip_removals;
8000 }
8001
8002 /*
8003 * Process removals.
8004 *
8005 * This is a counterpart of the above while loop which takes care of
8006 * removing an NSEC3 chain. It starts with determining whether the
8007 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8008 * NSEC chain by iterating over all nodes in the zone database and only
8009 * then goes on to remove NSEC3 records be iterating over all nodes
8010 * again and calling deletematchingnsec3() for each of them; otherwise,
8011 * it starts removing NSEC3 records immediately. Rules for processing
8012 * obscured nodes and interrupting work are the same as for the while
8013 * loop above.
8014 */
8015 LOCK_ZONE(zone);
8016 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8017 UNLOCK_ZONE(zone);
8018 first = true;
8019 buildnsecchain = false;
8020 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8021 LOCK_ZONE(zone);
8022 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8023 UNLOCK_ZONE(zone);
8024
8025 if (nsec3chain->db != db) {
8026 goto next_removechain;
8027 }
8028
8029 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8030 goto next_removechain;
8031 }
8032
8033 /*
8034 * Work out if we need to build a NSEC chain as a consequence
8035 * of removing this NSEC3 chain.
8036 */
8037 if (first && !updatensec &&
8038 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8039 {
8040 result = need_nsec_chain(db, version,
8041 &nsec3chain->nsec3param,
8042 &buildnsecchain);
8043 if (result != ISC_R_SUCCESS) {
8044 dnssec_log(zone, ISC_LOG_ERROR,
8045 "zone_nsec3chain:"
8046 "need_nsec_chain -> %s",
8047 dns_result_totext(result));
8048 goto failure;
8049 }
8050 }
8051
8052 if (first) {
8053 dnssec_log(zone, ISC_LOG_DEBUG(3),
8054 "zone_nsec3chain:buildnsecchain = %u\n",
8055 buildnsecchain);
8056 }
8057
8058 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8059 delegation = false;
8060
8061 if (!buildnsecchain) {
8062 /*
8063 * Delete the NSEC3PARAM record matching this chain.
8064 */
8065 if (first) {
8066 result = fixup_nsec3param(db, version,
8067 nsec3chain,
8068 true, privatetype,
8069 &param_diff);
8070 if (result != ISC_R_SUCCESS) {
8071 dnssec_log(zone, ISC_LOG_ERROR,
8072 "zone_nsec3chain:"
8073 "fixup_nsec3param -> %s",
8074 dns_result_totext(result));
8075 goto failure;
8076 }
8077 }
8078
8079 /*
8080 * Delete the NSEC3 records.
8081 */
8082 result = deletematchingnsec3(db, version, node, name,
8083 &nsec3chain->nsec3param,
8084 &nsec3_diff);
8085 if (result != ISC_R_SUCCESS) {
8086 dnssec_log(zone, ISC_LOG_ERROR,
8087 "zone_nsec3chain:"
8088 "deletematchingnsec3 -> %s",
8089 dns_result_totext(result));
8090 goto failure;
8091 }
8092 goto next_removenode;
8093 }
8094
8095 if (first) {
8096 dns_fixedname_t ffound;
8097 dns_name_t *found;
8098 found = dns_fixedname_initname(&ffound);
8099 result = dns_db_find(db, name, version,
8100 dns_rdatatype_soa,
8101 DNS_DBFIND_NOWILD, 0, NULL, found,
8102 NULL, NULL);
8103 if ((result == DNS_R_DELEGATION ||
8104 result == DNS_R_DNAME) &&
8105 !dns_name_equal(name, found))
8106 {
8107 /*
8108 * Remember the obscuring name so that
8109 * we skip all obscured names.
8110 */
8111 dns_name_copy(found, name, NULL);
8112 delegation = true;
8113 goto next_removenode;
8114 }
8115 }
8116
8117 /*
8118 * Check to see if this is a bottom of zone node.
8119 */
8120 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8121 if (result == ISC_R_NOTFOUND) {
8122 /* Empty node? */
8123 goto next_removenode;
8124 }
8125 if (result != ISC_R_SUCCESS) {
8126 goto failure;
8127 }
8128
8129 seen_soa = seen_ns = seen_dname = seen_nsec3 =
8130 seen_nsec = seen_rr = false;
8131 for (result = dns_rdatasetiter_first(iterator);
8132 result == ISC_R_SUCCESS;
8133 result = dns_rdatasetiter_next(iterator))
8134 {
8135 dns_rdatasetiter_current(iterator, &rdataset);
8136 if (rdataset.type == dns_rdatatype_soa) {
8137 seen_soa = true;
8138 } else if (rdataset.type == dns_rdatatype_ns) {
8139 seen_ns = true;
8140 } else if (rdataset.type == dns_rdatatype_dname) {
8141 seen_dname = true;
8142 } else if (rdataset.type == dns_rdatatype_nsec) {
8143 seen_nsec = true;
8144 } else if (rdataset.type == dns_rdatatype_nsec3) {
8145 seen_nsec3 = true;
8146 } else if (rdataset.type != dns_rdatatype_rrsig) {
8147 seen_rr = true;
8148 }
8149 dns_rdataset_disassociate(&rdataset);
8150 }
8151 dns_rdatasetiter_destroy(&iterator);
8152
8153 if (!seen_rr || seen_nsec3 || seen_nsec) {
8154 goto next_removenode;
8155 }
8156 if ((seen_ns && !seen_soa) || seen_dname) {
8157 delegation = true;
8158 }
8159
8160 /*
8161 * Add a NSEC record except at the origin.
8162 */
8163 if (!dns_name_equal(name, dns_db_origin(db))) {
8164 dns_dbiterator_pause(nsec3chain->dbiterator);
8165 CHECK(add_nsec(db, version, name, node, zone->minimum,
8166 delegation, &nsec_diff));
8167 signatures--;
8168 }
8169
8170 next_removenode:
8171 first = false;
8172 dns_db_detachnode(db, &node);
8173 do {
8174 result = dns_dbiterator_next(nsec3chain->dbiterator);
8175 if (result == ISC_R_NOMORE && buildnsecchain) {
8176 /*
8177 * The NSEC chain should now be built.
8178 * We can now remove the NSEC3 chain.
8179 */
8180 updatensec = true;
8181 goto same_removechain;
8182 }
8183 if (result == ISC_R_NOMORE) {
8184 LOCK_ZONE(zone);
8185 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8186 link);
8187 UNLOCK_ZONE(zone);
8188 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8189 dns_dbiterator_pause(nsec3chain->dbiterator);
8190 result = fixup_nsec3param(db, version,
8191 nsec3chain, false,
8192 privatetype,
8193 &param_diff);
8194 if (result != ISC_R_SUCCESS) {
8195 dnssec_log(zone, ISC_LOG_ERROR,
8196 "zone_nsec3chain:"
8197 "fixup_nsec3param -> %s",
8198 dns_result_totext(result));
8199 goto failure;
8200 }
8201 goto next_removechain;
8202 } else if (result != ISC_R_SUCCESS) {
8203 dnssec_log(zone, ISC_LOG_ERROR,
8204 "zone_nsec3chain:"
8205 "dns_dbiterator_next -> %s",
8206 dns_result_totext(result));
8207 goto failure;
8208 } else if (delegation) {
8209 dns_dbiterator_current(nsec3chain->dbiterator,
8210 &node, nextname);
8211 dns_db_detachnode(db, &node);
8212 if (!dns_name_issubdomain(nextname, name)) {
8213 break;
8214 }
8215 } else {
8216 break;
8217 }
8218 } while (1);
8219 continue;
8220
8221 same_removechain:
8222 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8223 buildnsecchain = false;
8224 first = true;
8225 continue;
8226
8227 next_removechain:
8228 dns_dbiterator_pause(nsec3chain->dbiterator);
8229 nsec3chain = nextnsec3chain;
8230 first = true;
8231 }
8232
8233 skip_removals:
8234 /*
8235 * We may need to update the NSEC/NSEC3 records for the zone apex.
8236 */
8237 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
8238 bool rebuild_nsec = false,
8239 rebuild_nsec3 = false;
8240 result = dns_db_getoriginnode(db, &node);
8241 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8242 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8243 if (result != ISC_R_SUCCESS) {
8244 dnssec_log(zone, ISC_LOG_ERROR,
8245 "zone_nsec3chain:dns_db_allrdatasets -> %s",
8246 dns_result_totext(result));
8247 goto failure;
8248 }
8249 for (result = dns_rdatasetiter_first(iterator);
8250 result == ISC_R_SUCCESS;
8251 result = dns_rdatasetiter_next(iterator))
8252 {
8253 dns_rdatasetiter_current(iterator, &rdataset);
8254 if (rdataset.type == dns_rdatatype_nsec) {
8255 rebuild_nsec = true;
8256 } else if (rdataset.type == dns_rdatatype_nsec3param) {
8257 rebuild_nsec3 = true;
8258 }
8259 dns_rdataset_disassociate(&rdataset);
8260 }
8261 dns_rdatasetiter_destroy(&iterator);
8262 dns_db_detachnode(db, &node);
8263
8264 if (rebuild_nsec) {
8265 if (nsec3chain != NULL) {
8266 dns_dbiterator_pause(nsec3chain->dbiterator);
8267 }
8268
8269 result = updatesecure(db, version, &zone->origin,
8270 zone->minimum, true,
8271 &nsec_diff);
8272 if (result != ISC_R_SUCCESS) {
8273 dnssec_log(zone, ISC_LOG_ERROR,
8274 "zone_nsec3chain:updatesecure -> %s",
8275 dns_result_totext(result));
8276 goto failure;
8277 }
8278 }
8279
8280 if (rebuild_nsec3) {
8281 if (nsec3chain != NULL) {
8282 dns_dbiterator_pause(nsec3chain->dbiterator);
8283 }
8284
8285 result = dns_nsec3_addnsec3s(db, version,
8286 dns_db_origin(db),
8287 zone->minimum, false,
8288 &nsec3_diff);
8289 if (result != ISC_R_SUCCESS) {
8290 dnssec_log(zone, ISC_LOG_ERROR,
8291 "zone_nsec3chain:"
8292 "dns_nsec3_addnsec3s -> %s",
8293 dns_result_totext(result));
8294 goto failure;
8295 }
8296 }
8297 }
8298
8299 /*
8300 * Add / update signatures for the NSEC3 records.
8301 */
8302 if (nsec3chain != NULL) {
8303 dns_dbiterator_pause(nsec3chain->dbiterator);
8304 }
8305 result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
8306 nkeys, zone, inception, expire, 0, now,
8307 check_ksk, keyset_kskonly, &zonediff);
8308 if (result != ISC_R_SUCCESS) {
8309 dnssec_log(zone, ISC_LOG_ERROR,
8310 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8311 dns_result_totext(result));
8312 goto failure;
8313 }
8314
8315 /*
8316 * We have changed the NSEC3PARAM or private RRsets
8317 * above so we need to update the signatures.
8318 */
8319 result = dns__zone_updatesigs(&param_diff, db, version, zone_keys,
8320 nkeys, zone, inception, expire, 0, now,
8321 check_ksk, keyset_kskonly, &zonediff);
8322 if (result != ISC_R_SUCCESS) {
8323 dnssec_log(zone, ISC_LOG_ERROR,
8324 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8325 dns_result_totext(result));
8326 goto failure;
8327 }
8328
8329 if (updatensec) {
8330 result = updatesecure(db, version, &zone->origin,
8331 zone->minimum, false, &nsec_diff);
8332 if (result != ISC_R_SUCCESS) {
8333 dnssec_log(zone, ISC_LOG_ERROR,
8334 "zone_nsec3chain:updatesecure -> %s",
8335 dns_result_totext(result));
8336 goto failure;
8337 }
8338 }
8339
8340 result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys,
8341 nkeys, zone, inception, expire, 0, now,
8342 check_ksk, keyset_kskonly, &zonediff);
8343 if (result != ISC_R_SUCCESS) {
8344 dnssec_log(zone, ISC_LOG_ERROR,
8345 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8346 dns_result_totext(result));
8347 goto failure;
8348 }
8349
8350 /*
8351 * If we made no effective changes to the zone then we can just
8352 * cleanup otherwise we need to increment the serial.
8353 */
8354 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
8355 /*
8356 * No need to call dns_db_closeversion() here as it is
8357 * called with commit = true below.
8358 */
8359 goto done;
8360 }
8361
8362 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
8363 &zonediff, zone_keys, nkeys, now, false);
8364 if (result != ISC_R_SUCCESS) {
8365 dnssec_log(zone, ISC_LOG_ERROR,
8366 "zone_nsec3chain:del_sigs -> %s",
8367 dns_result_totext(result));
8368 goto failure;
8369 }
8370
8371 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
8372 zone->updatemethod);
8373 if (result != ISC_R_SUCCESS) {
8374 dnssec_log(zone, ISC_LOG_ERROR,
8375 "zone_nsec3chain:update_soa_serial -> %s",
8376 dns_result_totext(result));
8377 goto failure;
8378 }
8379
8380 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
8381 zonediff.diff, zone_keys, nkeys, zone->mctx,
8382 inception, soaexpire, check_ksk, keyset_kskonly);
8383 if (result != ISC_R_SUCCESS) {
8384 dnssec_log(zone, ISC_LOG_ERROR,
8385 "zone_nsec3chain:add_sigs -> %s",
8386 dns_result_totext(result));
8387 goto failure;
8388 }
8389
8390 /* Write changes to journal file. */
8391 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
8392
8393 LOCK_ZONE(zone);
8394 zone_needdump(zone, DNS_DUMP_DELAY);
8395 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8396 UNLOCK_ZONE(zone);
8397
8398 done:
8399 /*
8400 * Pause all iterators so that dns_db_closeversion() can succeed.
8401 */
8402 LOCK_ZONE(zone);
8403 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8404 nsec3chain != NULL;
8405 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8406 {
8407 dns_dbiterator_pause(nsec3chain->dbiterator);
8408 }
8409 UNLOCK_ZONE(zone);
8410
8411 /*
8412 * Everything has succeeded. Commit the changes.
8413 * Unconditionally commit as zonediff.offline not checked above.
8414 */
8415 dns_db_closeversion(db, &version, true);
8416
8417 /*
8418 * Everything succeeded so we can clean these up now.
8419 */
8420 nsec3chain = ISC_LIST_HEAD(cleanup);
8421 while (nsec3chain != NULL) {
8422 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8423 dns_db_detach(&nsec3chain->db);
8424 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8425 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8426 nsec3chain = ISC_LIST_HEAD(cleanup);
8427 }
8428
8429 set_resigntime(zone);
8430
8431 failure:
8432 if (result != ISC_R_SUCCESS) {
8433 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
8434 dns_result_totext(result));
8435 }
8436
8437 /*
8438 * On error roll back the current nsec3chain.
8439 */
8440 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
8441 if (nsec3chain->done) {
8442 dns_db_detach(&nsec3chain->db);
8443 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8444 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8445 } else {
8446 result = dns_dbiterator_first(nsec3chain->dbiterator);
8447 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8448 dns_dbiterator_pause(nsec3chain->dbiterator);
8449 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
8450 }
8451 }
8452
8453 /*
8454 * Rollback the cleanup list.
8455 */
8456 nsec3chain = ISC_LIST_TAIL(cleanup);
8457 while (nsec3chain != NULL) {
8458 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8459 if (nsec3chain->done) {
8460 dns_db_detach(&nsec3chain->db);
8461 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8462 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8463 } else {
8464 LOCK_ZONE(zone);
8465 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
8466 UNLOCK_ZONE(zone);
8467 result = dns_dbiterator_first(nsec3chain->dbiterator);
8468 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8469 dns_dbiterator_pause(nsec3chain->dbiterator);
8470 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
8471 }
8472 nsec3chain = ISC_LIST_TAIL(cleanup);
8473 }
8474
8475 LOCK_ZONE(zone);
8476 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8477 nsec3chain != NULL;
8478 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8479 {
8480 dns_dbiterator_pause(nsec3chain->dbiterator);
8481 }
8482 UNLOCK_ZONE(zone);
8483
8484 dns_diff_clear(&param_diff);
8485 dns_diff_clear(&nsec3_diff);
8486 dns_diff_clear(&nsec_diff);
8487 dns_diff_clear(&_sig_diff);
8488
8489 if (iterator != NULL) {
8490 dns_rdatasetiter_destroy(&iterator);
8491 }
8492
8493 for (i = 0; i < nkeys; i++) {
8494 dst_key_free(&zone_keys[i]);
8495 }
8496
8497 if (node != NULL) {
8498 dns_db_detachnode(db, &node);
8499 }
8500 if (version != NULL) {
8501 dns_db_closeversion(db, &version, false);
8502 dns_db_detach(&db);
8503 } else if (db != NULL) {
8504 dns_db_detach(&db);
8505 }
8506
8507 LOCK_ZONE(zone);
8508 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
8509 isc_interval_t interval;
8510 if (zone->update_disabled || result != ISC_R_SUCCESS) {
8511 isc_interval_set(&interval, 60, 0); /* 1 minute */
8512 } else {
8513 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
8514 }
8515 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
8516 } else {
8517 isc_time_settoepoch(&zone->nsec3chaintime);
8518 }
8519 UNLOCK_ZONE(zone);
8520
8521 INSIST(version == NULL);
8522}
8523
8524/*%
8525 * Delete all RRSIG records with the given algorithm and keyid.
8526 * Remove the NSEC record and RRSIGs if nkeys is zero.
8527 * If all remaining RRsets are signed with the given algorithm
8528 * set *has_algp to true.
8529 */
8530static isc_result_t
8531del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
8532 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
8533 uint16_t keyid, bool *has_algp, dns_diff_t *diff)
8534{
8535 dns_rdata_rrsig_t rrsig;
8536 dns_rdataset_t rdataset;
8537 dns_rdatasetiter_t *iterator = NULL;
8538 isc_result_t result;
8539 bool alg_missed = false;
8540 bool alg_found = false;
8541
8542 char namebuf[DNS_NAME_FORMATSIZE];
8543 dns_name_format(name, namebuf, sizeof(namebuf));
8544
8545 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8546 if (result != ISC_R_SUCCESS) {
8547 if (result == ISC_R_NOTFOUND)
8548 result = ISC_R_SUCCESS;
8549 return (result);
8550 }
8551
8552 dns_rdataset_init(&rdataset);
8553 for (result = dns_rdatasetiter_first(iterator);
8554 result == ISC_R_SUCCESS;
8555 result = dns_rdatasetiter_next(iterator)) {
8556 bool has_alg = false;
8557 dns_rdatasetiter_current(iterator, &rdataset);
8558 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
8559 for (result = dns_rdataset_first(&rdataset);
8560 result == ISC_R_SUCCESS;
8561 result = dns_rdataset_next(&rdataset)) {
8562 dns_rdata_t rdata = DNS_RDATA_INIT;
8563 dns_rdataset_current(&rdataset, &rdata);
8564 CHECK(update_one_rr(db, version, diff,
8565 DNS_DIFFOP_DEL, name,
8566 rdataset.ttl, &rdata));
8567 }
8568 if (result != ISC_R_NOMORE)
8569 goto failure;
8570 dns_rdataset_disassociate(&rdataset);
8571 continue;
8572 }
8573 if (rdataset.type != dns_rdatatype_rrsig) {
8574 dns_rdataset_disassociate(&rdataset);
8575 continue;
8576 }
8577 for (result = dns_rdataset_first(&rdataset);
8578 result == ISC_R_SUCCESS;
8579 result = dns_rdataset_next(&rdataset))
8580 {
8581 dns_rdata_t rdata = DNS_RDATA_INIT;
8582 dns_rdataset_current(&rdataset, &rdata);
8583 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
8584 if (nkeys != 0 &&
8585 (rrsig.algorithm != algorithm ||
8586 rrsig.keyid != keyid))
8587 {
8588 if (rrsig.algorithm == algorithm) {
8589 has_alg = true;
8590 }
8591 continue;
8592 }
8593 CHECK(update_one_rr(db, version, diff,
8594 DNS_DIFFOP_DELRESIGN, name,
8595 rdataset.ttl, &rdata));
8596 }
8597 dns_rdataset_disassociate(&rdataset);
8598 if (result != ISC_R_NOMORE)
8599 break;
8600
8601 /*
8602 * After deleting, if there's still a signature for
8603 * 'algorithm', set alg_found; if not, set alg_missed.
8604 */
8605 if (has_alg) {
8606 alg_found = true;
8607 } else {
8608 alg_missed = true;
8609 }
8610 }
8611 if (result == ISC_R_NOMORE)
8612 result = ISC_R_SUCCESS;
8613
8614 /*
8615 * Set `has_algp` if the algorithm was found in every RRset:
8616 * i.e., found in at least one, and not missing from any.
8617 */
8618 *has_algp = (alg_found && !alg_missed);
8619 failure:
8620 if (dns_rdataset_isassociated(&rdataset))
8621 dns_rdataset_disassociate(&rdataset);
8622 dns_rdatasetiter_destroy(&iterator);
8623 return (result);
8624}
8625
8626/*
8627 * Incrementally sign the zone using the keys requested.
8628 * Builds the NSEC chain if required.
8629 */
8630static void
8631zone_sign(dns_zone_t *zone) {
8632 const char *me = "zone_sign";
8633 dns_db_t *db = NULL;
8634 dns_dbnode_t *node = NULL;
8635 dns_dbversion_t *version = NULL;
8636 dns_diff_t _sig_diff;
8637 dns_diff_t post_diff;
8638 dns__zonediff_t zonediff;
8639 dns_fixedname_t fixed;
8640 dns_fixedname_t nextfixed;
8641 dns_name_t *name, *nextname;
8642 dns_rdataset_t rdataset;
8643 dns_signing_t *signing, *nextsigning;
8644 dns_signinglist_t cleanup;
8645 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8646 int32_t signatures;
8647 bool check_ksk, keyset_kskonly, is_ksk;
8648 bool with_ksk, with_zsk;
8649 bool commit = false;
8650 bool is_bottom_of_zone;
8651 bool build_nsec = false;
8652 bool build_nsec3 = false;
8653 bool first;
8654 isc_result_t result;
8655 isc_stdtime_t now, inception, soaexpire, expire;
8656 uint32_t jitter, sigvalidityinterval, expiryinterval;
8657 unsigned int i, j;
8658 unsigned int nkeys = 0;
8659 uint32_t nodes;
8660
8661 ENTER;
8662
8663 dns_rdataset_init(&rdataset);
8664 name = dns_fixedname_initname(&fixed);
8665 nextname = dns_fixedname_initname(&nextfixed);
8666 dns_diff_init(zone->mctx, &_sig_diff);
8667 dns_diff_init(zone->mctx, &post_diff);
8668 zonediff_init(&zonediff, &_sig_diff);
8669 ISC_LIST_INIT(cleanup);
8670
8671 /*
8672 * Updates are disabled. Pause for 1 minute.
8673 */
8674 if (zone->update_disabled) {
8675 result = ISC_R_FAILURE;
8676 goto cleanup;
8677 }
8678
8679 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8680 if (zone->db != NULL) {
8681 dns_db_attach(zone->db, &db);
8682 }
8683 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8684 if (db == NULL) {
8685 result = ISC_R_FAILURE;
8686 goto cleanup;
8687 }
8688
8689 result = dns_db_newversion(db, &version);
8690 if (result != ISC_R_SUCCESS) {
8691 dnssec_log(zone, ISC_LOG_ERROR,
8692 "zone_sign:dns_db_newversion -> %s",
8693 dns_result_totext(result));
8694 goto cleanup;
8695 }
8696
8697 isc_stdtime_get(&now);
8698
8699 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8700 DNS_MAXZONEKEYS, zone_keys, &nkeys);
8701 if (result != ISC_R_SUCCESS) {
8702 dnssec_log(zone, ISC_LOG_ERROR,
8703 "zone_sign:dns__zone_findkeys -> %s",
8704 dns_result_totext(result));
8705 goto cleanup;
8706 }
8707
8708 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8709 inception = now - 3600; /* Allow for clock skew. */
8710 soaexpire = now + sigvalidityinterval;
8711 expiryinterval = dns_zone_getsigresigninginterval(zone);
8712 if (expiryinterval > sigvalidityinterval) {
8713 expiryinterval = sigvalidityinterval;
8714 } else {
8715 expiryinterval = sigvalidityinterval - expiryinterval;
8716 }
8717
8718 /*
8719 * Spread out signatures over time if they happen to be
8720 * clumped. We don't do this for each add_sigs() call as
8721 * we still want some clustering to occur.
8722 */
8723 if (sigvalidityinterval >= 3600U) {
8724 if (sigvalidityinterval > 7200U) {
8725 jitter = isc_random_uniform(expiryinterval);
8726 } else {
8727 jitter = isc_random_uniform(1200);
8728 }
8729 expire = soaexpire - jitter - 1;
8730 } else {
8731 expire = soaexpire - 1;
8732 }
8733
8734 /*
8735 * We keep pulling nodes off each iterator in turn until
8736 * we have no more nodes to pull off or we reach the limits
8737 * for this quantum.
8738 */
8739 nodes = zone->nodes;
8740 signatures = zone->signatures;
8741 signing = ISC_LIST_HEAD(zone->signing);
8742 first = true;
8743
8744 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8745 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8746
8747 /* Determine which type of chain to build */
8748 CHECK(dns_private_chains(db, version, zone->privatetype,
8749 &build_nsec, &build_nsec3));
8750
8751 /* If neither chain is found, default to NSEC */
8752 if (!build_nsec && !build_nsec3) {
8753 build_nsec = true;
8754 }
8755
8756 while (signing != NULL && nodes-- > 0 && signatures > 0) {
8757 bool has_alg = false;
8758 nextsigning = ISC_LIST_NEXT(signing, link);
8759
8760 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8761 if (signing->done || signing->db != zone->db) {
8762 /*
8763 * The zone has been reloaded. We will have
8764 * created new signings as part of the reload
8765 * process so we can destroy this one.
8766 */
8767 ISC_LIST_UNLINK(zone->signing, signing, link);
8768 ISC_LIST_APPEND(cleanup, signing, link);
8769 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8770 goto next_signing;
8771 }
8772 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8773
8774 if (signing->db != db) {
8775 goto next_signing;
8776 }
8777
8778 is_bottom_of_zone = false;
8779
8780 if (first && signing->deleteit) {
8781 /*
8782 * Remove the key we are deleting from consideration.
8783 */
8784 for (i = 0, j = 0; i < nkeys; i++) {
8785 /*
8786 * Find the key we want to remove.
8787 */
8788 if (ALG(zone_keys[i]) == signing->algorithm &&
8789 dst_key_id(zone_keys[i]) == signing->keyid)
8790 {
8791 if (KSK(zone_keys[i]))
8792 dst_key_free(&zone_keys[i]);
8793 continue;
8794 }
8795 zone_keys[j] = zone_keys[i];
8796 j++;
8797 }
8798 for (i = j; i < nkeys; i++) {
8799 zone_keys[i] = NULL;
8800 }
8801 nkeys = j;
8802 }
8803
8804 dns_dbiterator_current(signing->dbiterator, &node, name);
8805
8806 if (signing->deleteit) {
8807 dns_dbiterator_pause(signing->dbiterator);
8808 CHECK(del_sig(db, version, name, node, nkeys,
8809 signing->algorithm, signing->keyid,
8810 &has_alg, zonediff.diff));
8811 }
8812
8813 /*
8814 * On the first pass we need to check if the current node
8815 * has not been obscured.
8816 */
8817 if (first) {
8818 dns_fixedname_t ffound;
8819 dns_name_t *found;
8820 found = dns_fixedname_initname(&ffound);
8821 result = dns_db_find(db, name, version,
8822 dns_rdatatype_soa,
8823 DNS_DBFIND_NOWILD, 0, NULL, found,
8824 NULL, NULL);
8825 if ((result == DNS_R_DELEGATION ||
8826 result == DNS_R_DNAME) &&
8827 !dns_name_equal(name, found))
8828 {
8829 /*
8830 * Remember the obscuring name so that
8831 * we skip all obscured names.
8832 */
8833 dns_name_copy(found, name, NULL);
8834 is_bottom_of_zone = true;
8835 goto next_node;
8836 }
8837 }
8838
8839 /*
8840 * Process one node.
8841 */
8842 with_ksk = false;
8843 with_zsk = false;
8844 dns_dbiterator_pause(signing->dbiterator);
8845
8846 CHECK(check_if_bottom_of_zone(db, node, version,
8847 &is_bottom_of_zone));
8848
8849 for (i = 0; !has_alg && i < nkeys; i++) {
8850 bool both = false;
8851
8852 /*
8853 * Find the keys we want to sign with.
8854 */
8855 if (!dst_key_isprivate(zone_keys[i])) {
8856 continue;
8857 }
8858 /*
8859 * Should be redundant.
8860 */
8861 if (dst_key_inactive(zone_keys[i])) {
8862 continue;
8863 }
8864
8865 /*
8866 * When adding look for the specific key.
8867 */
8868 if (!signing->deleteit &&
8869 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
8870 dst_key_id(zone_keys[i]) != signing->keyid))
8871 {
8872 continue;
8873 }
8874
8875 /*
8876 * When deleting make sure we are properly signed
8877 * with the algorithm that was being removed.
8878 */
8879 if (signing->deleteit &&
8880 ALG(zone_keys[i]) != signing->algorithm)
8881 {
8882 continue;
8883 }
8884
8885 /*
8886 * Do we do KSK processing?
8887 */
8888 if (check_ksk && !REVOKE(zone_keys[i])) {
8889 bool have_ksk, have_nonksk;
8890 if (KSK(zone_keys[i])) {
8891 have_ksk = true;
8892 have_nonksk = false;
8893 } else {
8894 have_ksk = false;
8895 have_nonksk = true;
8896 }
8897 for (j = 0; j < nkeys; j++) {
8898 if (j == i ||
8899 (ALG(zone_keys[i]) !=
8900 ALG(zone_keys[j])))
8901 {
8902 continue;
8903 }
8904 if (!dst_key_isprivate(zone_keys[j])) {
8905 continue;
8906 }
8907 /*
8908 * Should be redundant.
8909 */
8910 if (dst_key_inactive(zone_keys[j])) {
8911 continue;
8912 }
8913 if (REVOKE(zone_keys[j])) {
8914 continue;
8915 }
8916 if (KSK(zone_keys[j])) {
8917 have_ksk = true;
8918 } else {
8919 have_nonksk = true;
8920 }
8921 both = have_ksk && have_nonksk;
8922 if (both) {
8923 break;
8924 }
8925 }
8926 }
8927 if (both || REVOKE(zone_keys[i])) {
8928 is_ksk = KSK(zone_keys[i]);
8929 } else {
8930 is_ksk = false;
8931 }
8932
8933 /*
8934 * If deleting signatures, we need to ensure that
8935 * the RRset is still signed at least once by a
8936 * KSK and a ZSK.
8937 */
8938 if (signing->deleteit && !is_ksk && with_zsk) {
8939 continue;
8940 }
8941
8942 if (signing->deleteit && is_ksk && with_ksk) {
8943 continue;
8944 }
8945
8946 CHECK(sign_a_node(db, name, node, version, build_nsec3,
8947 build_nsec, zone_keys[i], inception,
8948 expire, zone->minimum, is_ksk,
8949 (both && keyset_kskonly),
8950 is_bottom_of_zone, zonediff.diff,
8951 &signatures, zone->mctx));
8952 /*
8953 * If we are adding we are done. Look for other keys
8954 * of the same algorithm if deleting.
8955 */
8956 if (!signing->deleteit) {
8957 break;
8958 }
8959 if (!is_ksk) {
8960 with_zsk = true;
8961 }
8962 if (KSK(zone_keys[i])) {
8963 with_ksk = true;
8964 }
8965 }
8966
8967 /*
8968 * Go onto next node.
8969 */
8970 next_node:
8971 first = false;
8972 dns_db_detachnode(db, &node);
8973 do {
8974 result = dns_dbiterator_next(signing->dbiterator);
8975 if (result == ISC_R_NOMORE) {
8976 ISC_LIST_UNLINK(zone->signing, signing, link);
8977 ISC_LIST_APPEND(cleanup, signing, link);
8978 dns_dbiterator_pause(signing->dbiterator);
8979 if (nkeys != 0 && build_nsec) {
8980 /*
8981 * We have finished regenerating the
8982 * zone with a zone signing key.
8983 * The NSEC chain is now complete and
8984 * there is a full set of signatures
8985 * for the zone. We can now clear the
8986 * OPT bit from the NSEC record.
8987 */
8988 result = updatesecure(db, version,
8989 &zone->origin,
8990 zone->minimum,
8991 false,
8992 &post_diff);
8993 if (result != ISC_R_SUCCESS) {
8994 dnssec_log(zone, ISC_LOG_ERROR,
8995 "updatesecure -> %s",
8996 dns_result_totext(result));
8997 goto cleanup;
8998 }
8999 }
9000 result = updatesignwithkey(zone, signing,
9001 version,
9002 build_nsec3,
9003 zone->minimum,
9004 &post_diff);
9005 if (result != ISC_R_SUCCESS) {
9006 dnssec_log(zone, ISC_LOG_ERROR,
9007 "updatesignwithkey -> %s",
9008 dns_result_totext(result));
9009 goto cleanup;
9010 }
9011 build_nsec = false;
9012 goto next_signing;
9013 } else if (result != ISC_R_SUCCESS) {
9014 dnssec_log(zone, ISC_LOG_ERROR,
9015 "zone_sign:"
9016 "dns_dbiterator_next -> %s",
9017 dns_result_totext(result));
9018 goto cleanup;
9019 } else if (is_bottom_of_zone) {
9020 dns_dbiterator_current(signing->dbiterator,
9021 &node, nextname);
9022 dns_db_detachnode(db, &node);
9023 if (!dns_name_issubdomain(nextname, name)) {
9024 break;
9025 }
9026 } else {
9027 break;
9028 }
9029 } while (1);
9030 continue;
9031
9032 next_signing:
9033 dns_dbiterator_pause(signing->dbiterator);
9034 signing = nextsigning;
9035 first = true;
9036 }
9037
9038 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9039 result = dns__zone_updatesigs(&post_diff, db, version,
9040 zone_keys, nkeys, zone,
9041 inception, expire, 0, now,
9042 check_ksk, keyset_kskonly,
9043 &zonediff);
9044 if (result != ISC_R_SUCCESS) {
9045 dnssec_log(zone, ISC_LOG_ERROR,
9046 "zone_sign:dns__zone_updatesigs -> %s",
9047 dns_result_totext(result));
9048 goto cleanup;
9049 }
9050 }
9051
9052 /*
9053 * Have we changed anything?
9054 */
9055 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9056 if (zonediff.offline) {
9057 commit = true;
9058 }
9059 result = ISC_R_SUCCESS;
9060 goto pauseall;
9061 }
9062
9063 commit = true;
9064
9065 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9066 &zonediff, zone_keys, nkeys, now, false);
9067 if (result != ISC_R_SUCCESS) {
9068 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9069 dns_result_totext(result));
9070 goto cleanup;
9071 }
9072
9073 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
9074 zone->updatemethod);
9075 if (result != ISC_R_SUCCESS) {
9076 dnssec_log(zone, ISC_LOG_ERROR,
9077 "zone_sign:update_soa_serial -> %s",
9078 dns_result_totext(result));
9079 goto cleanup;
9080 }
9081
9082 /*
9083 * Generate maximum life time signatures so that the above loop
9084 * termination is sensible.
9085 */
9086 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
9087 zonediff.diff, zone_keys, nkeys, zone->mctx,
9088 inception, soaexpire, check_ksk, keyset_kskonly);
9089 if (result != ISC_R_SUCCESS) {
9090 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9091 dns_result_totext(result));
9092 goto cleanup;
9093 }
9094
9095 /*
9096 * Write changes to journal file.
9097 */
9098 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
9099
9100 pauseall:
9101 /*
9102 * Pause all iterators so that dns_db_closeversion() can succeed.
9103 */
9104 for (signing = ISC_LIST_HEAD(zone->signing);
9105 signing != NULL;
9106 signing = ISC_LIST_NEXT(signing, link))
9107 {
9108 dns_dbiterator_pause(signing->dbiterator);
9109 }
9110
9111 for (signing = ISC_LIST_HEAD(cleanup);
9112 signing != NULL;
9113 signing = ISC_LIST_NEXT(signing, link))
9114 {
9115 dns_dbiterator_pause(signing->dbiterator);
9116 }
9117
9118 /*
9119 * Everything has succeeded. Commit the changes.
9120 */
9121 dns_db_closeversion(db, &version, commit);
9122
9123 /*
9124 * Everything succeeded so we can clean these up now.
9125 */
9126 signing = ISC_LIST_HEAD(cleanup);
9127 while (signing != NULL) {
9128 ISC_LIST_UNLINK(cleanup, signing, link);
9129 dns_db_detach(&signing->db);
9130 dns_dbiterator_destroy(&signing->dbiterator);
9131 isc_mem_put(zone->mctx, signing, sizeof *signing);
9132 signing = ISC_LIST_HEAD(cleanup);
9133 }
9134
9135 set_resigntime(zone);
9136
9137 if (commit) {
9138 LOCK_ZONE(zone);
9139 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9140 zone_needdump(zone, DNS_DUMP_DELAY);
9141 UNLOCK_ZONE(zone);
9142 }
9143
9144 failure:
9145 if (result != ISC_R_SUCCESS) {
9146 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
9147 dns_result_totext(result));
9148 }
9149
9150 cleanup:
9151 /*
9152 * Pause all dbiterators.
9153 */
9154 for (signing = ISC_LIST_HEAD(zone->signing);
9155 signing != NULL;
9156 signing = ISC_LIST_NEXT(signing, link))
9157 {
9158 dns_dbiterator_pause(signing->dbiterator);
9159 }
9160
9161 /*
9162 * Rollback the cleanup list.
9163 */
9164 signing = ISC_LIST_HEAD(cleanup);
9165 while (signing != NULL) {
9166 ISC_LIST_UNLINK(cleanup, signing, link);
9167 ISC_LIST_PREPEND(zone->signing, signing, link);
9168 dns_dbiterator_first(signing->dbiterator);
9169 dns_dbiterator_pause(signing->dbiterator);
9170 signing = ISC_LIST_HEAD(cleanup);
9171 }
9172
9173 dns_diff_clear(&_sig_diff);
9174
9175 for (i = 0; i < nkeys; i++) {
9176 dst_key_free(&zone_keys[i]);
9177 }
9178
9179 if (node != NULL) {
9180 dns_db_detachnode(db, &node);
9181 }
9182
9183 if (version != NULL) {
9184 dns_db_closeversion(db, &version, false);
9185 dns_db_detach(&db);
9186 } else if (db != NULL) {
9187 dns_db_detach(&db);
9188 }
9189
9190 if (ISC_LIST_HEAD(zone->signing) != NULL) {
9191 isc_interval_t interval;
9192 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9193 isc_interval_set(&interval, 60, 0); /* 1 minute */
9194 } else {
9195 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9196 }
9197 isc_time_nowplusinterval(&zone->signingtime, &interval);
9198 } else {
9199 isc_time_settoepoch(&zone->signingtime);
9200 }
9201
9202 INSIST(version == NULL);
9203}
9204
9205static isc_result_t
9206normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
9207 unsigned char *data, int size)
9208{
9209 dns_rdata_dnskey_t dnskey;
9210 dns_rdata_keydata_t keydata;
9211 isc_buffer_t buf;
9212 isc_result_t result;
9213
9214 dns_rdata_reset(target);
9215 isc_buffer_init(&buf, data, size);
9216
9217 switch (rr->type) {
9218 case dns_rdatatype_dnskey:
9219 result = dns_rdata_tostruct(rr, &dnskey, NULL);
9220 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9221 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
9222 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9223 &dnskey, &buf);
9224 break;
9225 case dns_rdatatype_keydata:
9226 result = dns_rdata_tostruct(rr, &keydata, NULL);
9227 if (result == ISC_R_UNEXPECTEDEND)
9228 return (result);
9229 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9230 dns_keydata_todnskey(&keydata, &dnskey, NULL);
9231 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9232 &dnskey, &buf);
9233 break;
9234 default:
9235 INSIST(0);
9236 ISC_UNREACHABLE();
9237 }
9238 return (ISC_R_SUCCESS);
9239}
9240
9241/*
9242 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
9243 * a KEYDATA rdataset from the key zone.
9244 *
9245 * 'rr' contains either a DNSKEY record, or a KEYDATA record
9246 *
9247 * After normalizing keys to the same format (DNSKEY, with revoke bit
9248 * cleared), return true if a key that matches 'rr' is found in
9249 * 'rdset', or false if not.
9250 */
9251
9252static bool
9253matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
9254 unsigned char data1[4096], data2[4096];
9255 dns_rdata_t rdata, rdata1, rdata2;
9256 isc_result_t result;
9257
9258 dns_rdata_init(&rdata);
9259 dns_rdata_init(&rdata1);
9260 dns_rdata_init(&rdata2);
9261
9262 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
9263 if (result != ISC_R_SUCCESS)
9264 return (false);
9265
9266 for (result = dns_rdataset_first(rdset);
9267 result == ISC_R_SUCCESS;
9268 result = dns_rdataset_next(rdset)) {
9269 dns_rdata_reset(&rdata);
9270 dns_rdataset_current(rdset, &rdata);
9271 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
9272 if (result != ISC_R_SUCCESS)
9273 continue;
9274 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
9275 return (true);
9276 }
9277
9278 return (false);
9279}
9280
9281/*
9282 * Calculate the refresh interval for a keydata zone, per
9283 * RFC5011: MAX(1 hr,
9284 * MIN(15 days,
9285 * 1/2 * OrigTTL,
9286 * 1/2 * RRSigExpirationInterval))
9287 * or for retries: MAX(1 hr,
9288 * MIN(1 day,
9289 * 1/10 * OrigTTL,
9290 * 1/10 * RRSigExpirationInterval))
9291 */
9292static inline isc_stdtime_t
9293refresh_time(dns_keyfetch_t *kfetch, bool retry) {
9294 isc_result_t result;
9295 uint32_t t;
9296 dns_rdataset_t *rdset;
9297 dns_rdata_t sigrr = DNS_RDATA_INIT;
9298 dns_rdata_sig_t sig;
9299 isc_stdtime_t now;
9300
9301 isc_stdtime_get(&now);
9302
9303 if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
9304 rdset = &kfetch->dnskeysigset;
9305 else
9306 return (now + dns_zone_mkey_hour);
9307
9308 result = dns_rdataset_first(rdset);
9309 if (result != ISC_R_SUCCESS)
9310 return (now + dns_zone_mkey_hour);
9311
9312 dns_rdataset_current(rdset, &sigrr);
9313 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9314 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9315
9316 if (!retry) {
9317 t = sig.originalttl / 2;
9318
9319 if (isc_serial_gt(sig.timeexpire, now)) {
9320 uint32_t exp = (sig.timeexpire - now) / 2;
9321 if (t > exp)
9322 t = exp;
9323 }
9324
9325 if (t > (15 * dns_zone_mkey_day))
9326 t = (15 * dns_zone_mkey_day);
9327
9328 if (t < dns_zone_mkey_hour)
9329 t = dns_zone_mkey_hour;
9330 } else {
9331 t = sig.originalttl / 10;
9332
9333 if (isc_serial_gt(sig.timeexpire, now)) {
9334 uint32_t exp = (sig.timeexpire - now) / 10;
9335 if (t > exp)
9336 t = exp;
9337 }
9338
9339 if (t > dns_zone_mkey_day)
9340 t = dns_zone_mkey_day;
9341
9342 if (t < dns_zone_mkey_hour)
9343 t = dns_zone_mkey_hour;
9344 }
9345
9346 return (now + t);
9347}
9348
9349/*
9350 * This routine is called when no changes are needed in a KEYDATA
9351 * record except to simply update the refresh timer. Caller should
9352 * hold zone lock.
9353 */
9354static isc_result_t
9355minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
9356{
9357 isc_result_t result;
9358 isc_buffer_t keyb;
9359 unsigned char key_buf[4096];
9360 dns_rdata_t rdata = DNS_RDATA_INIT;
9361 dns_rdata_keydata_t keydata;
9362 dns_name_t *name;
9363 dns_zone_t *zone = kfetch->zone;
9364 isc_stdtime_t now;
9365
9366 name = dns_fixedname_name(&kfetch->name);
9367 isc_stdtime_get(&now);
9368
9369 for (result = dns_rdataset_first(&kfetch->keydataset);
9370 result == ISC_R_SUCCESS;
9371 result = dns_rdataset_next(&kfetch->keydataset)) {
9372 dns_rdata_reset(&rdata);
9373 dns_rdataset_current(&kfetch->keydataset, &rdata);
9374
9375 /* Delete old version */
9376 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
9377 name, 0, &rdata));
9378
9379 /* Update refresh timer */
9380 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
9381 if (result == ISC_R_UNEXPECTEDEND)
9382 continue;
9383 if (result != ISC_R_SUCCESS)
9384 goto failure;
9385 keydata.refresh = refresh_time(kfetch, true);
9386 set_refreshkeytimer(zone, &keydata, now, false);
9387
9388 dns_rdata_reset(&rdata);
9389 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9390 CHECK(dns_rdata_fromstruct(&rdata,
9391 zone->rdclass, dns_rdatatype_keydata,
9392 &keydata, &keyb));
9393
9394 /* Insert updated version */
9395 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
9396 name, 0, &rdata));
9397 }
9398 result = ISC_R_SUCCESS;
9399 failure:
9400 return (result);
9401}
9402
9403/*
9404 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
9405 */
9406static bool
9407revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
9408 isc_result_t result;
9409 dns_name_t *keyname;
9410 isc_mem_t *mctx;
9411 dns_rdata_t sigrr = DNS_RDATA_INIT;
9412 dns_rdata_t rr = DNS_RDATA_INIT;
9413 dns_rdata_rrsig_t sig;
9414 dns_rdata_dnskey_t dnskey;
9415 dst_key_t *dstkey = NULL;
9416 unsigned char key_buf[4096];
9417 isc_buffer_t keyb;
9418 bool answer = false;
9419
9420 REQUIRE(kfetch != NULL && keydata != NULL);
9421 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
9422
9423 keyname = dns_fixedname_name(&kfetch->name);
9424 mctx = kfetch->zone->view->mctx;
9425
9426 /* Generate a key from keydata */
9427 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9428 dns_keydata_todnskey(keydata, &dnskey, NULL);
9429 dns_rdata_fromstruct(&rr, keydata->common.rdclass,
9430 dns_rdatatype_dnskey, &dnskey, &keyb);
9431 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
9432 if (result != ISC_R_SUCCESS) {
9433 return (false);
9434 }
9435
9436 /* See if that key generated any of the signatures */
9437 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
9438 result == ISC_R_SUCCESS;
9439 result = dns_rdataset_next(&kfetch->dnskeysigset))
9440 {
9441 dns_fixedname_t fixed;
9442 dns_fixedname_init(&fixed);
9443
9444 dns_rdata_reset(&sigrr);
9445 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
9446 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9447 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9448
9449 if (dst_key_alg(dstkey) == sig.algorithm &&
9450 dst_key_rid(dstkey) == sig.keyid)
9451 {
9452 result = dns_dnssec_verify(keyname,
9453 &kfetch->dnskeyset,
9454 dstkey, false, 0, mctx,
9455 &sigrr,
9456 dns_fixedname_name(&fixed));
9457
9458 dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
9459 "Confirm revoked DNSKEY is self-signed: %s",
9460 dns_result_totext(result));
9461
9462 if (result == ISC_R_SUCCESS) {
9463 answer = true;
9464 break;
9465 }
9466 }
9467 }
9468
9469 dst_key_free(&dstkey);
9470 return (answer);
9471}
9472
9473/*
9474 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
9475 * anchors are being managed; scan the keyset, and update the key zone and the
9476 * local trust anchors according to RFC5011.
9477 */
9478static void
9479keyfetch_done(isc_task_t *task, isc_event_t *event) {
9480 isc_result_t result, eresult;
9481 dns_fetchevent_t *devent;
9482 dns_keyfetch_t *kfetch;
9483 dns_zone_t *zone;
9484 isc_mem_t *mctx = NULL;
9485 dns_keytable_t *secroots = NULL;
9486 dns_dbversion_t *ver = NULL;
9487 dns_diff_t diff;
9488 bool alldone = false;
9489 bool commit = false;
9490 dns_name_t *keyname;
9491 dns_rdata_t sigrr = DNS_RDATA_INIT;
9492 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
9493 dns_rdata_t keydatarr = DNS_RDATA_INIT;
9494 dns_rdata_rrsig_t sig;
9495 dns_rdata_dnskey_t dnskey;
9496 dns_rdata_keydata_t keydata;
9497 bool initializing;
9498 char namebuf[DNS_NAME_FORMATSIZE];
9499 unsigned char key_buf[4096];
9500 isc_buffer_t keyb;
9501 dst_key_t *dstkey;
9502 isc_stdtime_t now;
9503 int pending = 0;
9504 bool secure = false, initial = false;
9505 bool free_needed;
9506
9507 UNUSED(task);
9508 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
9509 INSIST(event->ev_arg != NULL);
9510
9511 kfetch = event->ev_arg;
9512 zone = kfetch->zone;
9513 isc_mem_attach(zone->mctx, &mctx);
9514 keyname = dns_fixedname_name(&kfetch->name);
9515
9516 devent = (dns_fetchevent_t *) event;
9517 eresult = devent->result;
9518
9519 /* Free resources which are not of interest */
9520 if (devent->node != NULL) {
9521 dns_db_detachnode(devent->db, &devent->node);
9522 }
9523 if (devent->db != NULL) {
9524 dns_db_detach(&devent->db);
9525 }
9526 isc_event_free(&event);
9527 dns_resolver_destroyfetch(&kfetch->fetch);
9528
9529 LOCK_ZONE(zone);
9530 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
9531 goto cleanup;
9532 }
9533
9534 isc_stdtime_get(&now);
9535 dns_name_format(keyname, namebuf, sizeof(namebuf));
9536
9537 result = dns_view_getsecroots(zone->view, &secroots);
9538 INSIST(result == ISC_R_SUCCESS);
9539
9540 dns_diff_init(mctx, &diff);
9541
9542 CHECK(dns_db_newversion(kfetch->db, &ver));
9543
9544 zone->refreshkeycount--;
9545 alldone = (zone->refreshkeycount == 0);
9546
9547 if (alldone) {
9548 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
9549 }
9550
9551 dnssec_log(zone, ISC_LOG_DEBUG(3),
9552 "Returned from key fetch in keyfetch_done() for '%s': %s",
9553 namebuf, dns_result_totext(eresult));
9554
9555 /* Fetch failed */
9556 if (eresult != ISC_R_SUCCESS ||
9557 !dns_rdataset_isassociated(&kfetch->dnskeyset))
9558 {
9559 dnssec_log(zone, ISC_LOG_WARNING,
9560 "Unable to fetch DNSKEY set '%s': %s",
9561 namebuf, dns_result_totext(eresult));
9562 CHECK(minimal_update(kfetch, ver, &diff));
9563 goto done;
9564 }
9565
9566 /* No RRSIGs found */
9567 if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
9568 dnssec_log(zone, ISC_LOG_WARNING,
9569 "No DNSKEY RRSIGs found for '%s': %s",
9570 namebuf, dns_result_totext(eresult));
9571 CHECK(minimal_update(kfetch, ver, &diff));
9572 goto done;
9573 }
9574
9575 /*
9576 * Clear any cached trust level, as we need to run validation
9577 * over again; trusted keys might have changed.
9578 */
9579 kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
9580
9581 /*
9582 * Validate the dnskeyset against the current trusted keys.
9583 */
9584 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
9585 result == ISC_R_SUCCESS;
9586 result = dns_rdataset_next(&kfetch->dnskeysigset))
9587 {
9588 dns_keynode_t *keynode = NULL;
9589
9590 dns_rdata_reset(&sigrr);
9591 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
9592 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9593 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9594
9595 result = dns_keytable_find(secroots, keyname, &keynode);
9596 while (result == ISC_R_SUCCESS) {
9597 dns_keynode_t *nextnode = NULL;
9598 dns_fixedname_t fixed;
9599 dns_fixedname_init(&fixed);
9600
9601 dstkey = dns_keynode_key(keynode);
9602 if (dstkey == NULL) {
9603 /* fail_secure() was called */
9604 break;
9605 }
9606
9607 if (dst_key_alg(dstkey) == sig.algorithm &&
9608 dst_key_id(dstkey) == sig.keyid)
9609 {
9610 result = dns_dnssec_verify(keyname,
9611 &kfetch->dnskeyset,
9612 dstkey, false,
9613 0,
9614 zone->view->mctx,
9615 &sigrr,
9616 dns_fixedname_name(
9617 &fixed));
9618
9619 dnssec_log(zone, ISC_LOG_DEBUG(3),
9620 "Verifying DNSKEY set for zone "
9621 "'%s' using key %d/%d: %s",
9622 namebuf, sig.keyid, sig.algorithm,
9623 dns_result_totext(result));
9624
9625 if (result == ISC_R_SUCCESS) {
9626 kfetch->dnskeyset.trust =
9627 dns_trust_secure;
9628 kfetch->dnskeysigset.trust =
9629 dns_trust_secure;
9630 secure = true;
9631 initial = dns_keynode_initial(keynode);
9632 dns_keynode_trust(keynode);
9633 break;
9634 }
9635 }
9636
9637 result = dns_keytable_nextkeynode(secroots,
9638 keynode, &nextnode);
9639 dns_keytable_detachkeynode(secroots, &keynode);
9640 keynode = nextnode;
9641 }
9642
9643 if (keynode != NULL) {
9644 dns_keytable_detachkeynode(secroots, &keynode);
9645 }
9646
9647 if (secure) {
9648 break;
9649 }
9650 }
9651
9652 /*
9653 * If we were not able to verify the answer using the current
9654 * trusted keys then all we can do is look at any revoked keys.
9655 */
9656 if (!secure) {
9657 dnssec_log(zone, ISC_LOG_INFO,
9658 "DNSKEY set for zone '%s' could not be verified "
9659 "with current keys", namebuf);
9660 }
9661
9662 /*
9663 * First scan keydataset to find keys that are not in dnskeyset
9664 * - Missing keys which are not scheduled for removal,
9665 * log a warning
9666 * - Missing keys which are scheduled for removal and
9667 * the remove hold-down timer has completed should
9668 * be removed from the key zone
9669 * - Missing keys whose acceptance timers have not yet
9670 * completed, log a warning and reset the acceptance
9671 * timer to 30 days in the future
9672 * - All keys not being removed have their refresh timers
9673 * updated
9674 */
9675 initializing = true;
9676 for (result = dns_rdataset_first(&kfetch->keydataset);
9677 result == ISC_R_SUCCESS;
9678 result = dns_rdataset_next(&kfetch->keydataset))
9679 {
9680 dns_keytag_t keytag;
9681
9682 dns_rdata_reset(&keydatarr);
9683 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
9684 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
9685 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9686
9687 dns_keydata_todnskey(&keydata, &dnskey, NULL);
9688 result = compute_tag(keyname, &dnskey, mctx, &keytag);
9689 if (result != ISC_R_SUCCESS) {
9690 /*
9691 * Skip if we cannot compute the key tag.
9692 * This may happen if the algorithm is unsupported
9693 */
9694 dns_zone_log(zone, ISC_LOG_ERROR,
9695 "Cannot compute tag for key in zone %s: %s "
9696 "(skipping)",
9697 namebuf, dns_result_totext(result));
9698 continue;
9699 }
9700 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9701
9702 /*
9703 * If any keydata record has a nonzero add holddown, then
9704 * there was a pre-existing trust anchor for this domain;
9705 * that means we are *not* initializing it and shouldn't
9706 * automatically trust all the keys we find at the zone apex.
9707 */
9708 initializing = initializing && (keydata.addhd == 0);
9709
9710 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
9711 bool deletekey = false;
9712
9713 if (!secure) {
9714 if (keydata.removehd != 0 &&
9715 keydata.removehd <= now)
9716 {
9717 deletekey = true;
9718 }
9719 } else if (keydata.addhd == 0) {
9720 deletekey = true;
9721 } else if (keydata.addhd > now) {
9722 dnssec_log(zone, ISC_LOG_INFO,
9723 "Pending key %d for zone %s "
9724 "unexpectedly missing "
9725 "restarting 30-day acceptance "
9726 "timer", keytag, namebuf);
9727 if (keydata.addhd < now + dns_zone_mkey_month) {
9728 keydata.addhd =
9729 now + dns_zone_mkey_month;
9730 }
9731 keydata.refresh = refresh_time(kfetch, false);
9732 } else if (keydata.removehd == 0) {
9733 dnssec_log(zone, ISC_LOG_INFO,
9734 "Active key %d for zone %s "
9735 "unexpectedly missing",
9736 keytag, namebuf);
9737 keydata.refresh = now + dns_zone_mkey_hour;
9738 } else if (keydata.removehd <= now) {
9739 deletekey = true;
9740 dnssec_log(zone, ISC_LOG_INFO,
9741 "Revoked key %d for zone %s "
9742 "missing: deleting from "
9743 "managed keys database",
9744 keytag, namebuf);
9745 } else {
9746 keydata.refresh = refresh_time(kfetch, false);
9747 }
9748
9749 if (secure || deletekey) {
9750 /* Delete old version */
9751 CHECK(update_one_rr(kfetch->db, ver, &diff,
9752 DNS_DIFFOP_DEL, keyname, 0,
9753 &keydatarr));
9754 }
9755
9756 if (!secure || deletekey) {
9757 continue;
9758 }
9759
9760 dns_rdata_reset(&keydatarr);
9761 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9762 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9763 dns_rdatatype_keydata,
9764 &keydata, &keyb);
9765
9766 /* Insert updated version */
9767 CHECK(update_one_rr(kfetch->db, ver, &diff,
9768 DNS_DIFFOP_ADD, keyname, 0,
9769 &keydatarr));
9770
9771 set_refreshkeytimer(zone, &keydata, now, false);
9772 }
9773 }
9774
9775 /*
9776 * Next scan dnskeyset:
9777 * - If new keys are found (i.e., lacking a match in keydataset)
9778 * add them to the key zone and set the acceptance timer
9779 * to 30 days in the future (or to immediately if we've
9780 * determined that we're initializing the zone for the
9781 * first time)
9782 * - Previously-known keys that have been revoked
9783 * must be scheduled for removal from the key zone (or,
9784 * if they hadn't been accepted as trust anchors yet
9785 * anyway, removed at once)
9786 * - Previously-known unrevoked keys whose acceptance timers
9787 * have completed are promoted to trust anchors
9788 * - All keys not being removed have their refresh
9789 * timers updated
9790 */
9791 for (result = dns_rdataset_first(&kfetch->dnskeyset);
9792 result == ISC_R_SUCCESS;
9793 result = dns_rdataset_next(&kfetch->dnskeyset))
9794 {
9795 bool revoked = false;
9796 bool newkey = false;
9797 bool updatekey = false;
9798 bool deletekey = false;
9799 bool trustkey = false;
9800 dns_keytag_t keytag;
9801
9802 dns_rdata_reset(&dnskeyrr);
9803 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
9804 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9805 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9806
9807 /* Skip ZSK's */
9808 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
9809 continue;
9810 }
9811
9812 result = compute_tag(keyname, &dnskey, mctx, &keytag);
9813 if (result != ISC_R_SUCCESS) {
9814 /*
9815 * Skip if we cannot compute the key tag.
9816 * This may happen if the algorithm is unsupported
9817 */
9818 dns_zone_log(zone, ISC_LOG_ERROR,
9819 "Cannot compute tag for key in zone %s: %s "
9820 "(skipping)",
9821 namebuf, dns_result_totext(result));
9822 continue;
9823 }
9824 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9825
9826 revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
9827
9828 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
9829 dns_rdata_reset(&keydatarr);
9830 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
9831 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
9832 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9833
9834 if (revoked && revocable(kfetch, &keydata)) {
9835 if (keydata.addhd > now) {
9836 /*
9837 * Key wasn't trusted yet, and now
9838 * it's been revoked? Just remove it
9839 */
9840 deletekey = true;
9841 dnssec_log(zone, ISC_LOG_INFO,
9842 "Pending key %d for "
9843 "zone %s is now revoked: "
9844 "deleting from the "
9845 "managed keys database",
9846 keytag, namebuf);
9847 } else if (keydata.removehd == 0) {
9848 /*
9849 * Remove key from secroots.
9850 */
9851 dns_view_untrust(zone->view, keyname,
9852 &dnskey, mctx);
9853
9854 /* If initializing, delete now */
9855 if (keydata.addhd == 0) {
9856 deletekey = true;
9857 } else {
9858 keydata.removehd = now +
9859 dns_zone_mkey_month;
9860 keydata.flags |=
9861 DNS_KEYFLAG_REVOKE;
9862 }
9863
9864 dnssec_log(zone, ISC_LOG_INFO,
9865 "Trusted key %d for "
9866 "zone %s is now revoked",
9867 keytag, namebuf);
9868 } else if (keydata.removehd < now) {
9869 /* Scheduled for removal */
9870 deletekey = true;
9871
9872 dnssec_log(zone, ISC_LOG_INFO,
9873 "Revoked key %d for "
9874 "zone %s removal timer "
9875 "complete: deleting from "
9876 "the managed keys database",
9877 keytag, namebuf);
9878 }
9879 } else if (revoked && keydata.removehd == 0) {
9880 dnssec_log(zone, ISC_LOG_WARNING,
9881 "Active key %d for zone "
9882 "%s is revoked but "
9883 "did not self-sign; "
9884 "ignoring", keytag, namebuf);
9885 continue;
9886 } else if (secure) {
9887 if (keydata.removehd != 0) {
9888 /*
9889 * Key isn't revoked--but it
9890 * seems it used to be.
9891 * Remove it now and add it
9892 * back as if it were a fresh key,
9893 * with a 30-day acceptance timer.
9894 */
9895 deletekey = true;
9896 newkey = true;
9897 keydata.removehd = 0;
9898 keydata.addhd =
9899 now + dns_zone_mkey_month;
9900
9901 dnssec_log(zone, ISC_LOG_INFO,
9902 "Revoked key %d for "
9903 "zone %s has returned: "
9904 "starting 30-day "
9905 "acceptance timer",
9906 keytag, namebuf);
9907 } else if (keydata.addhd > now) {
9908 pending++;
9909 } else if (keydata.addhd == 0) {
9910 keydata.addhd = now;
9911 }
9912
9913 if (keydata.addhd <= now) {
9914 trustkey = true;
9915 dnssec_log(zone, ISC_LOG_INFO,
9916 "Key %d for zone %s "
9917 "is now trusted (%s)",
9918 keytag, namebuf,
9919 initial
9920 ? "initializing key "
9921 "verified"
9922 : "acceptance timer "
9923 "complete");
9924 }
9925 } else if (keydata.addhd > now) {
9926 /*
9927 * Not secure, and key is pending:
9928 * reset the acceptance timer
9929 */
9930 pending++;
9931 keydata.addhd = now + dns_zone_mkey_month;
9932 dnssec_log(zone, ISC_LOG_INFO,
9933 "Pending key %d "
9934 "for zone %s was "
9935 "not validated: restarting "
9936 "30-day acceptance timer",
9937 keytag, namebuf);
9938 }
9939
9940 if (!deletekey && !newkey) {
9941 updatekey = true;
9942 }
9943 } else if (secure) {
9944 /*
9945 * Key wasn't in the key zone but it's
9946 * revoked now anyway, so just skip it
9947 */
9948 if (revoked) {
9949 continue;
9950 }
9951
9952 /* Key wasn't in the key zone: add it */
9953 newkey = true;
9954
9955 if (initializing) {
9956 dnssec_log(zone, ISC_LOG_WARNING,
9957 "Initializing automatic trust "
9958 "anchor management for zone '%s'; "
9959 "DNSKEY ID %d is now trusted, "
9960 "waiving the normal 30-day "
9961 "waiting period.",
9962 namebuf, keytag);
9963 trustkey = true;
9964 } else {
9965 dnssec_log(zone, ISC_LOG_INFO,
9966 "New key %d observed "
9967 "for zone '%s': "
9968 "starting 30-day "
9969 "acceptance timer",
9970 keytag, namebuf);
9971 }
9972 } else {
9973 /*
9974 * No previously known key, and the key is not
9975 * secure, so skip it.
9976 */
9977 continue;
9978 }
9979
9980 /* Delete old version */
9981 if (deletekey || !newkey) {
9982 CHECK(update_one_rr(kfetch->db, ver, &diff,
9983 DNS_DIFFOP_DEL, keyname, 0,
9984 &keydatarr));
9985 }
9986
9987 if (updatekey) {
9988 /* Set refresh timer */
9989 keydata.refresh = refresh_time(kfetch, false);
9990 dns_rdata_reset(&keydatarr);
9991 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9992 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9993 dns_rdatatype_keydata,
9994 &keydata, &keyb);
9995
9996 /* Insert updated version */
9997 CHECK(update_one_rr(kfetch->db, ver, &diff,
9998 DNS_DIFFOP_ADD, keyname, 0,
9999 &keydatarr));
10000 } else if (newkey) {
10001 /* Convert DNSKEY to KEYDATA */
10002 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10003 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10004 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10005 NULL);
10006 keydata.addhd = initializing
10007 ? now : now + dns_zone_mkey_month;
10008 keydata.refresh = refresh_time(kfetch, false);
10009 dns_rdata_reset(&keydatarr);
10010 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10011 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10012 dns_rdatatype_keydata,
10013 &keydata, &keyb);
10014
10015 /* Insert into key zone */
10016 CHECK(update_one_rr(kfetch->db, ver, &diff,
10017 DNS_DIFFOP_ADD, keyname, 0,
10018 &keydatarr));
10019 }
10020
10021 if (trustkey) {
10022 /* Trust this key. */
10023 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10024 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10025 trust_key(zone, keyname, &dnskey, false, mctx);
10026 }
10027
10028 if (secure && !deletekey) {
10029 INSIST(newkey || updatekey);
10030 set_refreshkeytimer(zone, &keydata, now, false);
10031 }
10032 }
10033
10034 /*
10035 * RFC5011 says, "A trust point that has all of its trust anchors
10036 * revoked is considered deleted and is treated as if the trust
10037 * point was never configured." But if someone revoked their
10038 * active key before the standby was trusted, that would mean the
10039 * zone would suddenly be nonsecured. We avoid this by checking to
10040 * see if there's pending keydata. If so, we put a null key in
10041 * the security roots; then all queries to the zone will fail.
10042 */
10043 if (pending != 0) {
10044 fail_secure(zone, keyname);
10045 }
10046
10047 done:
10048 if (!ISC_LIST_EMPTY(diff.tuples)) {
10049 /* Write changes to journal file. */
10050 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
10051 zone->updatemethod));
10052 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10053 commit = true;
10054
10055 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10056 zone_needdump(zone, 30);
10057 } else if (result == ISC_R_NOMORE) {
10058 /*
10059 * If "updatekey" was true for all keys found in the DNSKEY
10060 * response and the previous update of those keys happened
10061 * during the same second (only possible if a key refresh was
10062 * externally triggered), it may happen that all relevant
10063 * update_one_rr() calls will return ISC_R_SUCCESS, but
10064 * diff.tuples will remain empty. Reset result to
10065 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
10066 */
10067 result = ISC_R_SUCCESS;
10068 }
10069
10070 failure:
10071 if (result != ISC_R_SUCCESS) {
10072 dnssec_log(zone, ISC_LOG_ERROR,
10073 "error during managed-keys processing (%s): "
10074 "DNSSEC validation may be at risk",
10075 isc_result_totext(result));
10076 }
10077 dns_diff_clear(&diff);
10078 if (ver != NULL) {
10079 dns_db_closeversion(kfetch->db, &ver, commit);
10080 }
10081
10082 cleanup:
10083 dns_db_detach(&kfetch->db);
10084
10085 INSIST(zone->irefs > 0);
10086 zone->irefs--;
10087 kfetch->zone = NULL;
10088
10089 if (dns_rdataset_isassociated(&kfetch->keydataset)) {
10090 dns_rdataset_disassociate(&kfetch->keydataset);
10091 }
10092 if (dns_rdataset_isassociated(&kfetch->dnskeyset)) {
10093 dns_rdataset_disassociate(&kfetch->dnskeyset);
10094 }
10095 if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
10096 dns_rdataset_disassociate(&kfetch->dnskeysigset);
10097 }
10098
10099 dns_name_free(keyname, mctx);
10100 isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
10101 isc_mem_detach(&mctx);
10102
10103 if (secroots != NULL) {
10104 dns_keytable_detach(&secroots);
10105 }
10106
10107 free_needed = exit_check(zone);
10108 UNLOCK_ZONE(zone);
10109 if (free_needed) {
10110 zone_free(zone);
10111 }
10112
10113 INSIST(ver == NULL);
10114}
10115
10116/*
10117 * Refresh the data in the key zone. Initiate a fetch to get new DNSKEY
10118 * records from the zone apex.
10119 */
10120static void
10121zone_refreshkeys(dns_zone_t *zone) {
10122 const char me[] = "zone_refreshkeys";
10123 isc_result_t result;
10124 dns_rriterator_t rrit;
10125 dns_db_t *db = NULL;
10126 dns_dbversion_t *ver = NULL;
10127 dns_diff_t diff;
10128 dns_rdata_t rdata = DNS_RDATA_INIT;
10129 dns_rdata_keydata_t kd;
10130 isc_stdtime_t now;
10131 bool commit = false;
10132 bool fetching = false, fetch_err = false;
10133 bool timerset = false;
10134
10135 ENTER;
10136 REQUIRE(zone->db != NULL);
10137
10138 isc_stdtime_get(&now);
10139
10140 LOCK_ZONE(zone);
10141 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10142 isc_time_settoepoch(&zone->refreshkeytime);
10143 UNLOCK_ZONE(zone);
10144 return;
10145 }
10146
10147 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10148 dns_db_attach(zone->db, &db);
10149 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10150
10151 dns_diff_init(zone->mctx, &diff);
10152
10153 CHECK(dns_db_newversion(db, &ver));
10154
10155 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
10156
10157 dns_rriterator_init(&rrit, db, ver, 0);
10158 for (result = dns_rriterator_first(&rrit);
10159 result == ISC_R_SUCCESS;
10160 result = dns_rriterator_nextrrset(&rrit))
10161 {
10162 isc_stdtime_t timer = 0xffffffff;
10163 dns_name_t *name = NULL, *kname = NULL;
10164 dns_rdataset_t *kdset = NULL;
10165 dns_keyfetch_t *kfetch;
10166 uint32_t ttl;
10167
10168 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
10169 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
10170 !dns_rdataset_isassociated(kdset))
10171 {
10172 continue;
10173 }
10174
10175 /*
10176 * Scan the stored keys looking for ones that need
10177 * removal or refreshing
10178 */
10179 for (result = dns_rdataset_first(kdset);
10180 result == ISC_R_SUCCESS;
10181 result = dns_rdataset_next(kdset))
10182 {
10183 dns_rdata_reset(&rdata);
10184 dns_rdataset_current(kdset, &rdata);
10185 result = dns_rdata_tostruct(&rdata, &kd, NULL);
10186 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10187
10188 /* Removal timer expired? */
10189 if (kd.removehd != 0 && kd.removehd < now) {
10190 CHECK(update_one_rr(db, ver, &diff,
10191 DNS_DIFFOP_DEL, name, ttl,
10192 &rdata));
10193 continue;
10194 }
10195
10196 /* Acceptance timer expired? */
10197 if (kd.addhd <= now) {
10198 timer = kd.addhd;
10199 }
10200
10201 /* Or do we just need to refresh the keyset? */
10202 if (timer > kd.refresh) {
10203 timer = kd.refresh;
10204 }
10205
10206 set_refreshkeytimer(zone, &kd, now, false);
10207 timerset = true;
10208 }
10209
10210 if (timer > now) {
10211 continue;
10212 }
10213
10214 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
10215 if (kfetch == NULL) {
10216 fetch_err = true;
10217 goto failure;
10218 }
10219
10220 zone->refreshkeycount++;
10221 kfetch->zone = zone;
10222 zone->irefs++;
10223 INSIST(zone->irefs != 0);
10224 kname = dns_fixedname_initname(&kfetch->name);
10225 dns_name_dup(name, zone->mctx, kname);
10226 dns_rdataset_init(&kfetch->dnskeyset);
10227 dns_rdataset_init(&kfetch->dnskeysigset);
10228 dns_rdataset_init(&kfetch->keydataset);
10229 dns_rdataset_clone(kdset, &kfetch->keydataset);
10230 kfetch->db = NULL;
10231 dns_db_attach(db, &kfetch->db);
10232 kfetch->fetch = NULL;
10233
10234 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
10235 char namebuf[DNS_NAME_FORMATSIZE];
10236 dns_name_format(kname, namebuf,
10237 sizeof(namebuf));
10238 dnssec_log(zone, ISC_LOG_DEBUG(3),
10239 "Creating key fetch in "
10240 "zone_refreshkeys() for '%s'",
10241 namebuf);
10242 }
10243
10244 /*
10245 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is
10246 * not set and the cache still holds a non-expired, validated
10247 * version of the RRset being queried for by the time the
10248 * response is received, the cached RRset will be passed to
10249 * keyfetch_done() instead of the one received in the response
10250 * as the latter will have a lower trust level due to not being
10251 * validated until keyfetch_done() is called.
10252 */
10253
10254#ifdef ENABLE_AFL
10255 if (dns_fuzzing_resolver == false) {
10256#endif
10257 result = dns_resolver_createfetch(zone->view->resolver,
10258 kname, dns_rdatatype_dnskey,
10259 NULL, NULL, NULL, NULL, 0,
10260 DNS_FETCHOPT_NOVALIDATE |
10261 DNS_FETCHOPT_UNSHARED |
10262 DNS_FETCHOPT_NOCACHED,
10263 0, NULL, zone->task,
10264 keyfetch_done, kfetch,
10265 &kfetch->dnskeyset,
10266 &kfetch->dnskeysigset,
10267 &kfetch->fetch);
10268#ifdef ENABLE_AFL
10269 } else {
10270 result = ISC_R_FAILURE;
10271 }
10272#endif
10273 if (result == ISC_R_SUCCESS) {
10274 fetching = true;
10275 } else {
10276 zone->refreshkeycount--;
10277 zone->irefs--;
10278 dns_db_detach(&kfetch->db);
10279 dns_rdataset_disassociate(&kfetch->keydataset);
10280 dns_name_free(kname, zone->mctx);
10281 isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
10282 dnssec_log(zone, ISC_LOG_WARNING,
10283 "Failed to create fetch for DNSKEY update");
10284 fetch_err = true;
10285 }
10286 }
10287 if (!ISC_LIST_EMPTY(diff.tuples)) {
10288 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
10289 zone->updatemethod));
10290 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
10291 commit = true;
10292 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10293 zone_needdump(zone, 30);
10294 }
10295
10296 failure:
10297 if (fetch_err) {
10298 /*
10299 * Error during a key fetch; retry in an hour.
10300 */
10301 isc_time_t timenow, timethen;
10302 char timebuf[80];
10303
10304 TIME_NOW(&timenow);
10305 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
10306 zone->refreshkeytime = timethen;
10307 zone_settimer(zone, &timenow);
10308
10309 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
10310 dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
10311 timebuf);
10312 } else if (!timerset) {
10313 isc_time_settoepoch(&zone->refreshkeytime);
10314 }
10315
10316 if (!fetching) {
10317 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10318 }
10319
10320 dns_diff_clear(&diff);
10321 if (ver != NULL) {
10322 dns_rriterator_destroy(&rrit);
10323 dns_db_closeversion(db, &ver, commit);
10324 }
10325 dns_db_detach(&db);
10326
10327 UNLOCK_ZONE(zone);
10328
10329 INSIST(ver == NULL);
10330}
10331
10332static void
10333zone_maintenance(dns_zone_t *zone) {
10334 const char me[] = "zone_maintenance";
10335 isc_time_t now;
10336 isc_result_t result;
10337 bool dumping, load_pending;
10338
10339 REQUIRE(DNS_ZONE_VALID(zone));
10340 ENTER;
10341
10342 /*
10343 * Are we pending load/reload?
10344 */
10345 LOCK_ZONE(zone);
10346 load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
10347 UNLOCK_ZONE(zone);
10348
10349 if (load_pending) {
10350 return;
10351 }
10352
10353 /*
10354 * Configuring the view of this zone may have
10355 * failed, for example because the config file
10356 * had a syntax error. In that case, the view
10357 * adb or resolver will be NULL, and we had better not try
10358 * to do further maintenance on it.
10359 */
10360 if (zone->view == NULL || zone->view->adb == NULL)
10361 return;
10362
10363 TIME_NOW(&now);
10364
10365 /*
10366 * Expire check.
10367 */
10368 switch (zone->type) {
10369 case dns_zone_redirect:
10370 if (zone->masters == NULL)
10371 break;
10372 /* FALLTHROUGH */
10373 case dns_zone_slave:
10374 case dns_zone_mirror:
10375 case dns_zone_stub:
10376 LOCK_ZONE(zone);
10377 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
10378 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10379 zone_expire(zone);
10380 zone->refreshtime = now;
10381 }
10382 UNLOCK_ZONE(zone);
10383 break;
10384 default:
10385 break;
10386 }
10387
10388 /*
10389 * Up to date check.
10390 */
10391 switch (zone->type) {
10392 case dns_zone_redirect:
10393 if (zone->masters == NULL)
10394 break;
10395 /* FALLTHROUGH */
10396 case dns_zone_slave:
10397 case dns_zone_mirror:
10398 case dns_zone_stub:
10399 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
10400 isc_time_compare(&now, &zone->refreshtime) >= 0)
10401 dns_zone_refresh(zone);
10402 break;
10403 default:
10404 break;
10405 }
10406
10407 /*
10408 * Slaves send notifies before backing up to disk, masters after.
10409 */
10410 if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror) &&
10411 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
10412 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
10413 isc_time_compare(&now, &zone->notifytime) >= 0)
10414 zone_notify(zone, &now);
10415
10416 /*
10417 * Do we need to consolidate the backing store?
10418 */
10419 switch (zone->type) {
10420 case dns_zone_master:
10421 case dns_zone_slave:
10422 case dns_zone_mirror:
10423 case dns_zone_key:
10424 case dns_zone_redirect:
10425 case dns_zone_stub:
10426 LOCK_ZONE(zone);
10427 if (zone->masterfile != NULL &&
10428 isc_time_compare(&now, &zone->dumptime) >= 0 &&
10429 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10430 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
10431 dumping = was_dumping(zone);
10432 } else
10433 dumping = true;
10434 UNLOCK_ZONE(zone);
10435 if (!dumping) {
10436 result = zone_dump(zone, true); /* task locked */
10437 if (result != ISC_R_SUCCESS)
10438 dns_zone_log(zone, ISC_LOG_WARNING,
10439 "dump failed: %s",
10440 dns_result_totext(result));
10441 }
10442 break;
10443 default:
10444 break;
10445 }
10446
10447 /*
10448 * Master/redirect zones send notifies now, if needed
10449 */
10450 switch (zone->type) {
10451 case dns_zone_master:
10452 case dns_zone_redirect:
10453 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
10454 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
10455 isc_time_compare(&now, &zone->notifytime) >= 0)
10456 zone_notify(zone, &now);
10457 default:
10458 break;
10459 }
10460
10461 /*
10462 * Do we need to refresh keys?
10463 */
10464 switch (zone->type) {
10465 case dns_zone_key:
10466 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
10467 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10468 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10469 zone_refreshkeys(zone);
10470 }
10471 }
10472 break;
10473 case dns_zone_master:
10474 if (!isc_time_isepoch(&zone->refreshkeytime) &&
10475 isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
10476 zone->rss_event == NULL)
10477 zone_rekey(zone);
10478 default:
10479 break;
10480 }
10481
10482 switch (zone->type) {
10483 case dns_zone_master:
10484 case dns_zone_redirect:
10485 case dns_zone_slave:
10486 /*
10487 * Do we need to sign/resign some RRsets?
10488 */
10489 if (zone->rss_event != NULL)
10490 break;
10491 if (!isc_time_isepoch(&zone->signingtime) &&
10492 isc_time_compare(&now, &zone->signingtime) >= 0)
10493 zone_sign(zone);
10494 else if (!isc_time_isepoch(&zone->resigntime) &&
10495 isc_time_compare(&now, &zone->resigntime) >= 0)
10496 zone_resigninc(zone);
10497 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
10498 isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
10499 zone_nsec3chain(zone);
10500 /*
10501 * Do we need to issue a key expiry warning?
10502 */
10503 if (!isc_time_isepoch(&zone->keywarntime) &&
10504 isc_time_compare(&now, &zone->keywarntime) >= 0)
10505 set_key_expiry_warning(zone, zone->key_expiry,
10506 isc_time_seconds(&now));
10507 break;
10508
10509 default:
10510 break;
10511 }
10512 zone_settimer(zone, &now);
10513}
10514
10515void
10516dns_zone_markdirty(dns_zone_t *zone) {
10517 uint32_t serial;
10518 isc_result_t result = ISC_R_SUCCESS;
10519 dns_zone_t *secure = NULL;
10520
10521 /*
10522 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
10523 * could result in a deadlock due to a LOR so we will spin if we
10524 * can't obtain the both locks.
10525 */
10526 again:
10527 LOCK_ZONE(zone);
10528 if (zone->type == dns_zone_master) {
10529 if (inline_raw(zone)) {
10530 unsigned int soacount;
10531 secure = zone->secure;
10532 INSIST(secure != zone);
10533 TRYLOCK_ZONE(result, secure);
10534 if (result != ISC_R_SUCCESS) {
10535 UNLOCK_ZONE(zone);
10536 secure = NULL;
10537 isc_thread_yield();
10538 goto again;
10539 }
10540
10541 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10542 if (zone->db != NULL) {
10543 result = zone_get_from_db(zone, zone->db, NULL,
10544 &soacount, &serial,
10545 NULL, NULL, NULL,
10546 NULL, NULL);
10547 } else
10548 result = DNS_R_NOTLOADED;
10549 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10550 if (result == ISC_R_SUCCESS && soacount > 0U)
10551 zone_send_secureserial(zone, serial);
10552 }
10553
10554 /* XXXMPA make separate call back */
10555 if (result == ISC_R_SUCCESS)
10556 set_resigntime(zone);
10557 }
10558 if (secure != NULL)
10559 UNLOCK_ZONE(secure);
10560 zone_needdump(zone, DNS_DUMP_DELAY);
10561 UNLOCK_ZONE(zone);
10562}
10563
10564void
10565dns_zone_expire(dns_zone_t *zone) {
10566 REQUIRE(DNS_ZONE_VALID(zone));
10567
10568 LOCK_ZONE(zone);
10569 zone_expire(zone);
10570 UNLOCK_ZONE(zone);
10571}
10572
10573static void
10574zone_expire(dns_zone_t *zone) {
10575 /*
10576 * 'zone' locked by caller.
10577 */
10578
10579 REQUIRE(LOCKED_ZONE(zone));
10580
10581 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
10582
10583 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
10584 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
10585 zone->retry = DNS_ZONE_DEFAULTRETRY;
10586 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10587 zone_unload(zone);
10588}
10589
10590void
10591dns_zone_refresh(dns_zone_t *zone) {
10592 isc_interval_t i;
10593 uint32_t oldflags;
10594 unsigned int j;
10595 isc_result_t result;
10596
10597 REQUIRE(DNS_ZONE_VALID(zone));
10598
10599 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10600 return;
10601
10602 /*
10603 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
10604 * in progress at a time.
10605 */
10606
10607 LOCK_ZONE(zone);
10608 oldflags = zone->flags;
10609 if (zone->masterscnt == 0) {
10610 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
10611 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
10612 dns_zone_log(zone, ISC_LOG_ERROR,
10613 "cannot refresh: no masters");
10614 goto unlock;
10615 }
10616 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
10617 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10618 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10619 if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
10620 goto unlock;
10621
10622 /*
10623 * Set the next refresh time as if refresh check has failed.
10624 * Setting this to the retry time will do that. XXXMLG
10625 * If we are successful it will be reset using zone->refresh.
10626 */
10627 isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
10628 0);
10629 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
10630 if (result != ISC_R_SUCCESS)
10631 dns_zone_log(zone, ISC_LOG_WARNING,
10632 "isc_time_nowplusinterval() failed: %s",
10633 dns_result_totext(result));
10634
10635 /*
10636 * When lacking user-specified timer values from the SOA,
10637 * do exponential backoff of the retry time up to a
10638 * maximum of six hours.
10639 */
10640 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
10641 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
10642
10643 zone->curmaster = 0;
10644 for (j = 0; j < zone->masterscnt; j++)
10645 zone->mastersok[j] = false;
10646 /* initiate soa query */
10647 queue_soa_query(zone);
10648 unlock:
10649 UNLOCK_ZONE(zone);
10650}
10651
10652static void
10653zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
10654 isc_result_t result;
10655 int32_t journalsize;
10656 dns_dbversion_t *ver = NULL;
10657 uint64_t dbsize;
10658
10659 INSIST(LOCKED_ZONE(zone));
10660 if (inline_raw(zone))
10661 INSIST(LOCKED_ZONE(zone->secure));
10662
10663 journalsize = zone->journalsize;
10664 if (journalsize == -1) {
10665 journalsize = DNS_JOURNAL_SIZE_MAX;
10666 dns_db_currentversion(db, &ver);
10667 result = dns_db_getsize(db, ver, NULL, &dbsize);
10668 dns_db_closeversion(db, &ver, false);
10669 if (result != ISC_R_SUCCESS) {
10670 dns_zone_log(zone, ISC_LOG_ERROR,
10671 "zone_journal_compact: "
10672 "could not get zone size: %s",
10673 isc_result_totext(result));
10674 } else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
10675 journalsize = (int32_t)dbsize * 2;
10676 }
10677 }
10678 zone_debuglog(zone, "zone_journal_compact", 1,
10679 "target journal size %d", journalsize);
10680 result = dns_journal_compact(zone->mctx, zone->journal,
10681 serial, journalsize);
10682 switch (result) {
10683 case ISC_R_SUCCESS:
10684 case ISC_R_NOSPACE:
10685 case ISC_R_NOTFOUND:
10686 dns_zone_log(zone, ISC_LOG_DEBUG(3),
10687 "dns_journal_compact: %s",
10688 dns_result_totext(result));
10689 break;
10690 default:
10691 dns_zone_log(zone, ISC_LOG_ERROR,
10692 "dns_journal_compact failed: %s",
10693 dns_result_totext(result));
10694 break;
10695 }
10696}
10697
10698isc_result_t
10699dns_zone_flush(dns_zone_t *zone) {
10700 isc_result_t result = ISC_R_SUCCESS;
10701 bool dumping;
10702
10703 REQUIRE(DNS_ZONE_VALID(zone));
10704
10705 LOCK_ZONE(zone);
10706 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
10707 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10708 zone->masterfile != NULL) {
10709 result = ISC_R_ALREADYRUNNING;
10710 dumping = was_dumping(zone);
10711 } else
10712 dumping = true;
10713 UNLOCK_ZONE(zone);
10714 if (!dumping)
10715 result = zone_dump(zone, true); /* Unknown task. */
10716 return (result);
10717}
10718
10719isc_result_t
10720dns_zone_dump(dns_zone_t *zone) {
10721 isc_result_t result = ISC_R_ALREADYRUNNING;
10722 bool dumping;
10723
10724 REQUIRE(DNS_ZONE_VALID(zone));
10725
10726 LOCK_ZONE(zone);
10727 dumping = was_dumping(zone);
10728 UNLOCK_ZONE(zone);
10729 if (!dumping)
10730 result = zone_dump(zone, false); /* Unknown task. */
10731 return (result);
10732}
10733
10734static void
10735zone_needdump(dns_zone_t *zone, unsigned int delay) {
10736 const char me[] = "zone_needdump";
10737 isc_time_t dumptime;
10738 isc_time_t now;
10739
10740 /*
10741 * 'zone' locked by caller
10742 */
10743
10744 REQUIRE(DNS_ZONE_VALID(zone));
10745 REQUIRE(LOCKED_ZONE(zone));
10746 ENTER;
10747
10748 /*
10749 * Do we have a place to dump to and are we loaded?
10750 */
10751 if (zone->masterfile == NULL ||
10752 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
10753 return;
10754
10755 TIME_NOW(&now);
10756 /* add some noise */
10757 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
10758
10759 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10760 if (isc_time_isepoch(&zone->dumptime) ||
10761 isc_time_compare(&zone->dumptime, &dumptime) > 0)
10762 zone->dumptime = dumptime;
10763 if (zone->task != NULL)
10764 zone_settimer(zone, &now);
10765}
10766
10767static void
10768dump_done(void *arg, isc_result_t result) {
10769 const char me[] = "dump_done";
10770 dns_zone_t *zone = arg;
10771 dns_zone_t *secure = NULL;
10772 dns_db_t *db;
10773 dns_dbversion_t *version;
10774 bool again = false;
10775 bool compact = false;
10776 uint32_t serial;
10777 isc_result_t tresult;
10778
10779 REQUIRE(DNS_ZONE_VALID(zone));
10780
10781 ENTER;
10782
10783 if (result == ISC_R_SUCCESS && zone->journal != NULL) {
10784 /*
10785 * We don't own these, zone->dctx must stay valid.
10786 */
10787 db = dns_dumpctx_db(zone->dctx);
10788 version = dns_dumpctx_version(zone->dctx);
10789 tresult = dns_db_getsoaserial(db, version, &serial);
10790
10791 /*
10792 * Handle lock order inversion.
10793 */
10794 again:
10795 LOCK_ZONE(zone);
10796 if (inline_raw(zone)) {
10797 secure = zone->secure;
10798 INSIST(secure != zone);
10799 TRYLOCK_ZONE(result, secure);
10800 if (result != ISC_R_SUCCESS) {
10801 UNLOCK_ZONE(zone);
10802 secure = NULL;
10803 isc_thread_yield();
10804 goto again;
10805 }
10806 }
10807
10808 /*
10809 * If there is a secure version of this zone
10810 * use its serial if it is less than ours.
10811 */
10812 if (tresult == ISC_R_SUCCESS && secure != NULL) {
10813 uint32_t sserial;
10814 isc_result_t mresult;
10815
10816 ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
10817 if (secure->db != NULL) {
10818 mresult = dns_db_getsoaserial(zone->secure->db,
10819 NULL, &sserial);
10820 if (mresult == ISC_R_SUCCESS &&
10821 isc_serial_lt(sserial, serial))
10822 serial = sserial;
10823 }
10824 ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
10825 }
10826 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
10827 dns_db_t *zdb = NULL;
10828 if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
10829 zone_journal_compact(zone, zdb, serial);
10830 dns_db_detach(&zdb);
10831 }
10832 } else if (tresult == ISC_R_SUCCESS) {
10833 compact = true;
10834 zone->compact_serial = serial;
10835 }
10836 if (secure != NULL)
10837 UNLOCK_ZONE(secure);
10838 UNLOCK_ZONE(zone);
10839 }
10840
10841 LOCK_ZONE(zone);
10842 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
10843 if (compact)
10844 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
10845 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
10846 /*
10847 * Try again in a short while.
10848 */
10849 zone_needdump(zone, DNS_DUMP_DELAY);
10850 } else if (result == ISC_R_SUCCESS &&
10851 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
10852 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10853 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10854 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10855 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
10856 isc_time_settoepoch(&zone->dumptime);
10857 again = true;
10858 } else if (result == ISC_R_SUCCESS)
10859 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
10860
10861 if (zone->dctx != NULL)
10862 dns_dumpctx_detach(&zone->dctx);
10863 zonemgr_putio(&zone->writeio);
10864 UNLOCK_ZONE(zone);
10865 if (again)
10866 (void)zone_dump(zone, false);
10867 dns_zone_idetach(&zone);
10868}
10869
10870static isc_result_t
10871zone_dump(dns_zone_t *zone, bool compact) {
10872 const char me[] = "zone_dump";
10873 isc_result_t result;
10874 dns_dbversion_t *version = NULL;
10875 bool again;
10876 dns_db_t *db = NULL;
10877 char *masterfile = NULL;
10878 dns_masterformat_t masterformat = dns_masterformat_none;
10879
10880/*
10881 * 'compact' MUST only be set if we are task locked.
10882 */
10883
10884 REQUIRE(DNS_ZONE_VALID(zone));
10885 ENTER;
10886
10887 redo:
10888 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10889 if (zone->db != NULL)
10890 dns_db_attach(zone->db, &db);
10891 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10892 LOCK_ZONE(zone);
10893 if (zone->masterfile != NULL) {
10894 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
10895 masterformat = zone->masterformat;
10896 }
10897 UNLOCK_ZONE(zone);
10898 if (db == NULL) {
10899 result = DNS_R_NOTLOADED;
10900 goto fail;
10901 }
10902 if (masterfile == NULL) {
10903 result = DNS_R_NOMASTERFILE;
10904 goto fail;
10905 }
10906
10907 if (compact && zone->type != dns_zone_stub) {
10908 dns_zone_t *dummy = NULL;
10909 LOCK_ZONE(zone);
10910 zone_iattach(zone, &dummy);
10911 result = zonemgr_getio(zone->zmgr, false, zone->task,
10912 zone_gotwritehandle, zone,
10913 &zone->writeio);
10914 if (result != ISC_R_SUCCESS)
10915 zone_idetach(&dummy);
10916 else
10917 result = DNS_R_CONTINUE;
10918 UNLOCK_ZONE(zone);
10919 } else {
10920 const dns_master_style_t *output_style;
10921
10922 dns_masterrawheader_t rawdata;
10923 dns_db_currentversion(db, &version);
10924 dns_master_initrawheader(&rawdata);
10925 if (inline_secure(zone))
10926 get_raw_serial(zone->raw, &rawdata);
10927 if (zone->type == dns_zone_key)
10928 output_style = &dns_master_style_keyzone;
10929 else
10930 output_style = &dns_master_style_default;
10931 result = dns_master_dump(zone->mctx, db, version,
10932 output_style, masterfile,
10933 masterformat, &rawdata);
10934 dns_db_closeversion(db, &version, false);
10935 }
10936 fail:
10937 if (db != NULL)
10938 dns_db_detach(&db);
10939 if (masterfile != NULL)
10940 isc_mem_free(zone->mctx, masterfile);
10941 masterfile = NULL;
10942
10943 if (result == DNS_R_CONTINUE)
10944 return (ISC_R_SUCCESS); /* XXXMPA */
10945
10946 again = false;
10947 LOCK_ZONE(zone);
10948 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
10949 if (result != ISC_R_SUCCESS) {
10950 /*
10951 * Try again in a short while.
10952 */
10953 zone_needdump(zone, DNS_DUMP_DELAY);
10954 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
10955 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10956 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10957 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10958 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
10959 isc_time_settoepoch(&zone->dumptime);
10960 again = true;
10961 } else
10962 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
10963 UNLOCK_ZONE(zone);
10964 if (again)
10965 goto redo;
10966
10967 return (result);
10968}
10969
10970static isc_result_t
10971dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
10972 dns_masterformat_t format, const uint32_t rawversion)
10973{
10974 isc_result_t result;
10975 dns_dbversion_t *version = NULL;
10976 dns_db_t *db = NULL;
10977 dns_masterrawheader_t rawdata;
10978
10979 REQUIRE(DNS_ZONE_VALID(zone));
10980
10981 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10982 if (zone->db != NULL)
10983 dns_db_attach(zone->db, &db);
10984 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10985 if (db == NULL)
10986 return (DNS_R_NOTLOADED);
10987
10988 dns_db_currentversion(db, &version);
10989 dns_master_initrawheader(&rawdata);
10990 if (rawversion == 0)
10991 rawdata.flags |= DNS_MASTERRAW_COMPAT;
10992 else if (inline_secure(zone))
10993 get_raw_serial(zone->raw, &rawdata);
10994 else if (zone->sourceserialset) {
10995 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
10996 rawdata.sourceserial = zone->sourceserial;
10997 }
10998 result = dns_master_dumptostream(zone->mctx, db, version, style,
10999 format, &rawdata, fd);
11000 dns_db_closeversion(db, &version, false);
11001 dns_db_detach(&db);
11002 return (result);
11003}
11004
11005isc_result_t
11006dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
11007 const dns_master_style_t *style,
11008 const uint32_t rawversion)
11009{
11010 return (dumptostream(zone, fd, style, format, rawversion));
11011}
11012
11013void
11014dns_zone_unload(dns_zone_t *zone) {
11015 REQUIRE(DNS_ZONE_VALID(zone));
11016
11017 LOCK_ZONE(zone);
11018 zone_unload(zone);
11019 UNLOCK_ZONE(zone);
11020}
11021
11022static void
11023notify_cancel(dns_zone_t *zone) {
11024 dns_notify_t *notify;
11025
11026 /*
11027 * 'zone' locked by caller.
11028 */
11029
11030 REQUIRE(LOCKED_ZONE(zone));
11031
11032 for (notify = ISC_LIST_HEAD(zone->notifies);
11033 notify != NULL;
11034 notify = ISC_LIST_NEXT(notify, link)) {
11035 if (notify->find != NULL)
11036 dns_adb_cancelfind(notify->find);
11037 if (notify->request != NULL)
11038 dns_request_cancel(notify->request);
11039 }
11040}
11041
11042static void
11043forward_cancel(dns_zone_t *zone) {
11044 dns_forward_t *forward;
11045
11046 /*
11047 * 'zone' locked by caller.
11048 */
11049
11050 REQUIRE(LOCKED_ZONE(zone));
11051
11052 for (forward = ISC_LIST_HEAD(zone->forwards);
11053 forward != NULL;
11054 forward = ISC_LIST_NEXT(forward, link)) {
11055 if (forward->request != NULL)
11056 dns_request_cancel(forward->request);
11057 }
11058}
11059
11060static void
11061zone_unload(dns_zone_t *zone) {
11062 /*
11063 * 'zone' locked by caller.
11064 */
11065
11066 REQUIRE(LOCKED_ZONE(zone));
11067
11068 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11069 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11070 if (zone->writeio != NULL)
11071 zonemgr_cancelio(zone->writeio);
11072
11073 if (zone->dctx != NULL)
11074 dns_dumpctx_cancel(zone->dctx);
11075 }
11076 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11077 zone_detachdb(zone);
11078 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11079 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
11080 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11081
11082 if (zone->type == dns_zone_mirror) {
11083 dns_zone_log(zone, ISC_LOG_INFO,
11084 "mirror zone is no longer in use; "
11085 "reverting to normal recursion");
11086 }
11087}
11088
11089void
11090dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
11091 REQUIRE(DNS_ZONE_VALID(zone));
11092 REQUIRE(val > 0);
11093
11094 zone->minrefresh = val;
11095}
11096
11097void
11098dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
11099 REQUIRE(DNS_ZONE_VALID(zone));
11100 REQUIRE(val > 0);
11101
11102 zone->maxrefresh = val;
11103}
11104
11105void
11106dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
11107 REQUIRE(DNS_ZONE_VALID(zone));
11108 REQUIRE(val > 0);
11109
11110 zone->minretry = val;
11111}
11112
11113void
11114dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
11115 REQUIRE(DNS_ZONE_VALID(zone));
11116 REQUIRE(val > 0);
11117
11118 zone->maxretry = val;
11119}
11120
11121uint32_t
11122dns_zone_getmaxrecords(dns_zone_t *zone) {
11123 REQUIRE(DNS_ZONE_VALID(zone));
11124
11125 return (zone->maxrecords);
11126}
11127
11128void
11129dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
11130 REQUIRE(DNS_ZONE_VALID(zone));
11131
11132 zone->maxrecords = val;
11133}
11134
11135static bool
11136notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
11137 isc_sockaddr_t *addr, dns_tsigkey_t *key)
11138{
11139 dns_notify_t *notify;
11140 dns_zonemgr_t *zmgr;
11141 isc_result_t result;
11142
11143 for (notify = ISC_LIST_HEAD(zone->notifies);
11144 notify != NULL;
11145 notify = ISC_LIST_NEXT(notify, link)) {
11146 if (notify->request != NULL)
11147 continue;
11148 if (name != NULL && dns_name_dynamic(&notify->ns) &&
11149 dns_name_equal(name, &notify->ns))
11150 goto requeue;
11151 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
11152 notify->key == key)
11153 goto requeue;
11154 }
11155 return (false);
11156
11157requeue:
11158 /*
11159 * If we are enqueued on the startup ratelimiter and this is
11160 * not a startup notify, re-enqueue on the normal notify
11161 * ratelimiter.
11162 */
11163 if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
11164 (notify->flags & DNS_NOTIFY_STARTUP) != 0) {
11165 zmgr = notify->zone->zmgr;
11166 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
11167 notify->event);
11168 if (result != ISC_R_SUCCESS)
11169 return (true);
11170
11171 notify->flags &= ~DNS_NOTIFY_STARTUP;
11172 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
11173 notify->zone->task,
11174 &notify->event);
11175 if (result != ISC_R_SUCCESS) {
11176 isc_event_free(&notify->event);
11177 return (false);
11178 }
11179 }
11180
11181 return (true);
11182}
11183
11184static bool
11185notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
11186 dns_tsigkey_t *key = NULL;
11187 isc_sockaddr_t src;
11188 isc_sockaddr_t any;
11189 bool isself;
11190 isc_netaddr_t dstaddr;
11191 isc_result_t result;
11192
11193 if (zone->view == NULL || zone->isself == NULL)
11194 return (false);
11195
11196 switch (isc_sockaddr_pf(dst)) {
11197 case PF_INET:
11198 src = zone->notifysrc4;
11199 isc_sockaddr_any(&any);
11200 break;
11201 case PF_INET6:
11202 src = zone->notifysrc6;
11203 isc_sockaddr_any6(&any);
11204 break;
11205 default:
11206 return (false);
11207 }
11208
11209 /*
11210 * When sending from any the kernel will assign a source address
11211 * that matches the destination address.
11212 */
11213 if (isc_sockaddr_eqaddr(&any, &src))
11214 src = *dst;
11215
11216 isc_netaddr_fromsockaddr(&dstaddr, dst);
11217 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
11218 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
11219 return (false);
11220 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
11221 zone->isselfarg);
11222 if (key != NULL)
11223 dns_tsigkey_detach(&key);
11224 return (isself);
11225}
11226
11227static void
11228notify_destroy(dns_notify_t *notify, bool locked) {
11229 isc_mem_t *mctx;
11230
11231 REQUIRE(DNS_NOTIFY_VALID(notify));
11232
11233 if (notify->zone != NULL) {
11234 if (!locked)
11235 LOCK_ZONE(notify->zone);
11236 REQUIRE(LOCKED_ZONE(notify->zone));
11237 if (ISC_LINK_LINKED(notify, link))
11238 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
11239 if (!locked)
11240 UNLOCK_ZONE(notify->zone);
11241 if (locked)
11242 zone_idetach(&notify->zone);
11243 else
11244 dns_zone_idetach(&notify->zone);
11245 }
11246 if (notify->find != NULL)
11247 dns_adb_destroyfind(&notify->find);
11248 if (notify->request != NULL)
11249 dns_request_destroy(&notify->request);
11250 if (dns_name_dynamic(&notify->ns))
11251 dns_name_free(&notify->ns, notify->mctx);
11252 if (notify->key != NULL)
11253 dns_tsigkey_detach(&notify->key);
11254 mctx = notify->mctx;
11255 isc_mem_put(notify->mctx, notify, sizeof(*notify));
11256 isc_mem_detach(&mctx);
11257}
11258
11259static isc_result_t
11260notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
11261 dns_notify_t *notify;
11262
11263 REQUIRE(notifyp != NULL && *notifyp == NULL);
11264
11265 notify = isc_mem_get(mctx, sizeof(*notify));
11266 if (notify == NULL)
11267 return (ISC_R_NOMEMORY);
11268
11269 notify->mctx = NULL;
11270 isc_mem_attach(mctx, &notify->mctx);
11271 notify->flags = flags;
11272 notify->zone = NULL;
11273 notify->find = NULL;
11274 notify->request = NULL;
11275 notify->key = NULL;
11276 notify->event = NULL;
11277 isc_sockaddr_any(&notify->dst);
11278 dns_name_init(&notify->ns, NULL);
11279 ISC_LINK_INIT(notify, link);
11280 notify->magic = NOTIFY_MAGIC;
11281 *notifyp = notify;
11282 return (ISC_R_SUCCESS);
11283}
11284
11285/*
11286 * XXXAG should check for DNS_ZONEFLG_EXITING
11287 */
11288static void
11289process_adb_event(isc_task_t *task, isc_event_t *ev) {
11290 dns_notify_t *notify;
11291 isc_eventtype_t result;
11292
11293 UNUSED(task);
11294
11295 notify = ev->ev_arg;
11296 REQUIRE(DNS_NOTIFY_VALID(notify));
11297 INSIST(task == notify->zone->task);
11298 result = ev->ev_type;
11299 isc_event_free(&ev);
11300 if (result == DNS_EVENT_ADBMOREADDRESSES) {
11301 dns_adb_destroyfind(&notify->find);
11302 notify_find_address(notify);
11303 return;
11304 }
11305 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
11306 LOCK_ZONE(notify->zone);
11307 notify_send(notify);
11308 UNLOCK_ZONE(notify->zone);
11309 }
11310 notify_destroy(notify, false);
11311}
11312
11313static void
11314notify_find_address(dns_notify_t *notify) {
11315 isc_result_t result;
11316 unsigned int options;
11317
11318 REQUIRE(DNS_NOTIFY_VALID(notify));
11319 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
11320 DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
11321
11322 if (notify->zone->view->adb == NULL)
11323 goto destroy;
11324
11325 result = dns_adb_createfind(notify->zone->view->adb,
11326 notify->zone->task,
11327 process_adb_event, notify,
11328 &notify->ns, dns_rootname, 0,
11329 options, 0, NULL,
11330 notify->zone->view->dstport,
11331 0, NULL, &notify->find);
11332
11333 /* Something failed? */
11334 if (result != ISC_R_SUCCESS)
11335 goto destroy;
11336
11337 /* More addresses pending? */
11338 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
11339 return;
11340
11341 /* We have as many addresses as we can get. */
11342 LOCK_ZONE(notify->zone);
11343 notify_send(notify);
11344 UNLOCK_ZONE(notify->zone);
11345
11346 destroy:
11347 notify_destroy(notify, false);
11348}
11349
11350
11351static isc_result_t
11352notify_send_queue(dns_notify_t *notify, bool startup) {
11353 isc_event_t *e;
11354 isc_result_t result;
11355
11356 INSIST(notify->event == NULL);
11357 e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
11358 notify_send_toaddr, notify, sizeof(isc_event_t));
11359 if (e == NULL)
11360 return (ISC_R_NOMEMORY);
11361 if (startup)
11362 notify->event = e;
11363 e->ev_arg = notify;
11364 e->ev_sender = NULL;
11365 result = isc_ratelimiter_enqueue(startup
11366 ? notify->zone->zmgr->startupnotifyrl
11367 : notify->zone->zmgr->notifyrl,
11368 notify->zone->task, &e);
11369 if (result != ISC_R_SUCCESS) {
11370 isc_event_free(&e);
11371 notify->event = NULL;
11372 }
11373 return (result);
11374}
11375
11376static void
11377notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
11378 dns_notify_t *notify;
11379 isc_result_t result;
11380 dns_message_t *message = NULL;
11381 isc_netaddr_t dstip;
11382 dns_tsigkey_t *key = NULL;
11383 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11384 isc_sockaddr_t src;
11385 unsigned int options, timeout;
11386 bool have_notifysource = false;
11387 bool have_notifydscp = false;
11388 isc_dscp_t dscp = -1;
11389
11390 notify = event->ev_arg;
11391 REQUIRE(DNS_NOTIFY_VALID(notify));
11392
11393 UNUSED(task);
11394
11395 LOCK_ZONE(notify->zone);
11396
11397 notify->event = NULL;
11398
11399 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
11400 result = ISC_R_CANCELED;
11401 goto cleanup;
11402 }
11403
11404 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
11405 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
11406 notify->zone->view->requestmgr == NULL ||
11407 notify->zone->db == NULL) {
11408 result = ISC_R_CANCELED;
11409 goto cleanup;
11410 }
11411
11412 /*
11413 * The raw IPv4 address should also exist. Don't send to the
11414 * mapped form.
11415 */
11416 if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
11417 IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
11418 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
11419 notify_log(notify->zone, ISC_LOG_DEBUG(3),
11420 "notify: ignoring IPv6 mapped IPV4 address: %s",
11421 addrbuf);
11422 result = ISC_R_CANCELED;
11423 goto cleanup;
11424 }
11425
11426 result = notify_createmessage(notify->zone, notify->flags, &message);
11427 if (result != ISC_R_SUCCESS)
11428 goto cleanup;
11429
11430 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
11431 if (notify->key != NULL) {
11432 /* Transfer ownership of key */
11433 key = notify->key;
11434 notify->key = NULL;
11435 } else {
11436 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
11437 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
11438 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11439 notify_log(notify->zone, ISC_LOG_ERROR,
11440 "NOTIFY to %s not sent. "
11441 "Peer TSIG key lookup failure.", addrbuf);
11442 goto cleanup_message;
11443 }
11444 }
11445
11446 /* XXX: should we log the tsig key too? */
11447 notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
11448 addrbuf);
11449 options = 0;
11450 if (notify->zone->view->peers != NULL) {
11451 dns_peer_t *peer = NULL;
11452 bool usetcp = false;
11453 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
11454 &dstip, &peer);
11455 if (result == ISC_R_SUCCESS) {
11456 result = dns_peer_getnotifysource(peer, &src);
11457 if (result == ISC_R_SUCCESS)
11458 have_notifysource = true;
11459 dns_peer_getnotifydscp(peer, &dscp);
11460 if (dscp != -1)
11461 have_notifydscp = true;
11462 result = dns_peer_getforcetcp(peer, &usetcp);
11463 if (result == ISC_R_SUCCESS && usetcp)
11464 options |= DNS_FETCHOPT_TCP;
11465 }
11466 }
11467 switch (isc_sockaddr_pf(&notify->dst)) {
11468 case PF_INET:
11469 if (!have_notifysource)
11470 src = notify->zone->notifysrc4;
11471 if (!have_notifydscp)
11472 dscp = notify->zone->notifysrc4dscp;
11473 break;
11474 case PF_INET6:
11475 if (!have_notifysource)
11476 src = notify->zone->notifysrc6;
11477 if (!have_notifydscp)
11478 dscp = notify->zone->notifysrc6dscp;
11479 break;
11480 default:
11481 result = ISC_R_NOTIMPLEMENTED;
11482 goto cleanup_key;
11483 }
11484 timeout = 15;
11485 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
11486 timeout = 30;
11487 result = dns_request_createvia(notify->zone->view->requestmgr,
11488 message, &src, &notify->dst, dscp,
11489 options, key, timeout * 3, timeout,
11490 0, notify->zone->task, notify_done,
11491 notify, &notify->request);
11492 if (result == ISC_R_SUCCESS) {
11493 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
11494 inc_stats(notify->zone,
11495 dns_zonestatscounter_notifyoutv4);
11496 } else {
11497 inc_stats(notify->zone,
11498 dns_zonestatscounter_notifyoutv6);
11499 }
11500 }
11501
11502 cleanup_key:
11503 if (key != NULL)
11504 dns_tsigkey_detach(&key);
11505 cleanup_message:
11506 dns_message_destroy(&message);
11507 cleanup:
11508 UNLOCK_ZONE(notify->zone);
11509 isc_event_free(&event);
11510 if (result != ISC_R_SUCCESS)
11511 notify_destroy(notify, false);
11512}
11513
11514static void
11515notify_send(dns_notify_t *notify) {
11516 dns_adbaddrinfo_t *ai;
11517 isc_sockaddr_t dst;
11518 isc_result_t result;
11519 dns_notify_t *newnotify = NULL;
11520 unsigned int flags;
11521 bool startup;
11522
11523 /*
11524 * Zone lock held by caller.
11525 */
11526 REQUIRE(DNS_NOTIFY_VALID(notify));
11527 REQUIRE(LOCKED_ZONE(notify->zone));
11528
11529 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING))
11530 return;
11531
11532 for (ai = ISC_LIST_HEAD(notify->find->list);
11533 ai != NULL;
11534 ai = ISC_LIST_NEXT(ai, publink)) {
11535 dst = ai->sockaddr;
11536 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
11537 NULL))
11538 continue;
11539 if (notify_isself(notify->zone, &dst))
11540 continue;
11541 newnotify = NULL;
11542 flags = notify->flags & DNS_NOTIFY_NOSOA;
11543 result = notify_create(notify->mctx, flags, &newnotify);
11544 if (result != ISC_R_SUCCESS)
11545 goto cleanup;
11546 zone_iattach(notify->zone, &newnotify->zone);
11547 ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
11548 newnotify->dst = dst;
11549 startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
11550 result = notify_send_queue(newnotify, startup);
11551 if (result != ISC_R_SUCCESS)
11552 goto cleanup;
11553 newnotify = NULL;
11554 }
11555
11556 cleanup:
11557 if (newnotify != NULL)
11558 notify_destroy(newnotify, true);
11559}
11560
11561void
11562dns_zone_notify(dns_zone_t *zone) {
11563 isc_time_t now;
11564
11565 REQUIRE(DNS_ZONE_VALID(zone));
11566
11567 LOCK_ZONE(zone);
11568 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11569
11570 TIME_NOW(&now);
11571 zone_settimer(zone, &now);
11572 UNLOCK_ZONE(zone);
11573}
11574
11575static void
11576zone_notify(dns_zone_t *zone, isc_time_t *now) {
11577 dns_dbnode_t *node = NULL;
11578 dns_db_t *zonedb = NULL;
11579 dns_dbversion_t *version = NULL;
11580 dns_name_t *origin = NULL;
11581 dns_name_t master;
11582 dns_rdata_ns_t ns;
11583 dns_rdata_soa_t soa;
11584 uint32_t serial;
11585 dns_rdata_t rdata = DNS_RDATA_INIT;
11586 dns_rdataset_t nsrdset;
11587 dns_rdataset_t soardset;
11588 isc_result_t result;
11589 unsigned int i;
11590 isc_sockaddr_t dst;
11591 bool isqueued;
11592 dns_notifytype_t notifytype;
11593 unsigned int flags = 0;
11594 bool loggednotify = false;
11595 bool startup;
11596
11597 REQUIRE(DNS_ZONE_VALID(zone));
11598
11599 LOCK_ZONE(zone);
11600 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11601 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11602 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
11603 notifytype = zone->notifytype;
11604 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
11605 UNLOCK_ZONE(zone);
11606
11607 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11608 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11609 return;
11610
11611 if (notifytype == dns_notifytype_no)
11612 return;
11613
11614 if (notifytype == dns_notifytype_masteronly &&
11615 zone->type != dns_zone_master)
11616 return;
11617
11618 origin = &zone->origin;
11619
11620 /*
11621 * If the zone is dialup we are done as we don't want to send
11622 * the current soa so as to force a refresh query.
11623 */
11624 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
11625 flags |= DNS_NOTIFY_NOSOA;
11626
11627 /*
11628 * Record that this was a notify due to starting up.
11629 */
11630 if (startup)
11631 flags |= DNS_NOTIFY_STARTUP;
11632
11633 /*
11634 * Get SOA RRset.
11635 */
11636 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11637 if (zone->db != NULL)
11638 dns_db_attach(zone->db, &zonedb);
11639 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11640 if (zonedb == NULL)
11641 return;
11642 dns_db_currentversion(zonedb, &version);
11643 result = dns_db_findnode(zonedb, origin, false, &node);
11644 if (result != ISC_R_SUCCESS)
11645 goto cleanup1;
11646
11647 dns_rdataset_init(&soardset);
11648 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
11649 dns_rdatatype_none, 0, &soardset, NULL);
11650 if (result != ISC_R_SUCCESS)
11651 goto cleanup2;
11652
11653 /*
11654 * Find serial and master server's name.
11655 */
11656 dns_name_init(&master, NULL);
11657 result = dns_rdataset_first(&soardset);
11658 if (result != ISC_R_SUCCESS)
11659 goto cleanup3;
11660 dns_rdataset_current(&soardset, &rdata);
11661 result = dns_rdata_tostruct(&rdata, &soa, NULL);
11662 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11663 dns_rdata_reset(&rdata);
11664 result = dns_name_dup(&soa.origin, zone->mctx, &master);
11665 serial = soa.serial;
11666 dns_rdataset_disassociate(&soardset);
11667 if (result != ISC_R_SUCCESS)
11668 goto cleanup3;
11669
11670 /*
11671 * Enqueue notify requests for 'also-notify' servers.
11672 */
11673 LOCK_ZONE(zone);
11674 for (i = 0; i < zone->notifycnt; i++) {
11675 dns_tsigkey_t *key = NULL;
11676 dns_notify_t *notify = NULL;
11677
11678 if ((zone->notifykeynames != NULL) &&
11679 (zone->notifykeynames[i] != NULL)) {
11680 dns_view_t *view = dns_zone_getview(zone);
11681 dns_name_t *keyname = zone->notifykeynames[i];
11682 (void)dns_view_gettsig(view, keyname, &key);
11683 }
11684
11685 dst = zone->notify[i];
11686 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
11687 if (key != NULL)
11688 dns_tsigkey_detach(&key);
11689 continue;
11690 }
11691
11692 result = notify_create(zone->mctx, flags, &notify);
11693 if (result != ISC_R_SUCCESS) {
11694 if (key != NULL)
11695 dns_tsigkey_detach(&key);
11696 continue;
11697 }
11698
11699 zone_iattach(zone, &notify->zone);
11700 notify->dst = dst;
11701
11702 INSIST(notify->key == NULL);
11703
11704 if (key != NULL) {
11705 notify->key = key;
11706 key = NULL;
11707 }
11708
11709 ISC_LIST_APPEND(zone->notifies, notify, link);
11710 result = notify_send_queue(notify, startup);
11711 if (result != ISC_R_SUCCESS)
11712 notify_destroy(notify, true);
11713 if (!loggednotify) {
11714 notify_log(zone, ISC_LOG_INFO,
11715 "sending notifies (serial %u)",
11716 serial);
11717 loggednotify = true;
11718 }
11719 }
11720 UNLOCK_ZONE(zone);
11721
11722 if (notifytype == dns_notifytype_explicit)
11723 goto cleanup3;
11724
11725 /*
11726 * Process NS RRset to generate notifies.
11727 */
11728
11729 dns_rdataset_init(&nsrdset);
11730 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
11731 dns_rdatatype_none, 0, &nsrdset, NULL);
11732 if (result != ISC_R_SUCCESS)
11733 goto cleanup3;
11734
11735 result = dns_rdataset_first(&nsrdset);
11736 while (result == ISC_R_SUCCESS) {
11737 dns_notify_t *notify = NULL;
11738
11739 dns_rdataset_current(&nsrdset, &rdata);
11740 result = dns_rdata_tostruct(&rdata, &ns, NULL);
11741 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11742 dns_rdata_reset(&rdata);
11743 /*
11744 * Don't notify the master server unless explicitly
11745 * configured to do so.
11746 */
11747 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
11748 dns_name_compare(&master, &ns.name) == 0) {
11749 result = dns_rdataset_next(&nsrdset);
11750 continue;
11751 }
11752
11753 if (!loggednotify) {
11754 notify_log(zone, ISC_LOG_INFO,
11755 "sending notifies (serial %u)",
11756 serial);
11757 loggednotify = true;
11758 }
11759
11760 LOCK_ZONE(zone);
11761 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
11762 UNLOCK_ZONE(zone);
11763 if (isqueued) {
11764 result = dns_rdataset_next(&nsrdset);
11765 continue;
11766 }
11767 result = notify_create(zone->mctx, flags, &notify);
11768 if (result != ISC_R_SUCCESS)
11769 continue;
11770 dns_zone_iattach(zone, &notify->zone);
11771 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
11772 if (result != ISC_R_SUCCESS) {
11773 LOCK_ZONE(zone);
11774 notify_destroy(notify, true);
11775 UNLOCK_ZONE(zone);
11776 continue;
11777 }
11778 LOCK_ZONE(zone);
11779 ISC_LIST_APPEND(zone->notifies, notify, link);
11780 UNLOCK_ZONE(zone);
11781 notify_find_address(notify);
11782 result = dns_rdataset_next(&nsrdset);
11783 }
11784 dns_rdataset_disassociate(&nsrdset);
11785
11786 cleanup3:
11787 if (dns_name_dynamic(&master))
11788 dns_name_free(&master, zone->mctx);
11789 cleanup2:
11790 dns_db_detachnode(zonedb, &node);
11791 cleanup1:
11792 dns_db_closeversion(zonedb, &version, false);
11793 dns_db_detach(&zonedb);
11794}
11795
11796/***
11797 *** Private
11798 ***/
11799
11800static inline isc_result_t
11801save_nsrrset(dns_message_t *message, dns_name_t *name,
11802 dns_db_t *db, dns_dbversion_t *version)
11803{
11804 dns_rdataset_t *nsrdataset = NULL;
11805 dns_rdataset_t *rdataset = NULL;
11806 dns_dbnode_t *node = NULL;
11807 dns_rdata_ns_t ns;
11808 isc_result_t result;
11809 dns_rdata_t rdata = DNS_RDATA_INIT;
11810
11811 /*
11812 * Extract NS RRset from message.
11813 */
11814 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
11815 dns_rdatatype_ns, dns_rdatatype_none,
11816 NULL, &nsrdataset);
11817 if (result != ISC_R_SUCCESS)
11818 goto fail;
11819
11820 /*
11821 * Add NS rdataset.
11822 */
11823 result = dns_db_findnode(db, name, true, &node);
11824 if (result != ISC_R_SUCCESS)
11825 goto fail;
11826 result = dns_db_addrdataset(db, node, version, 0,
11827 nsrdataset, 0, NULL);
11828 dns_db_detachnode(db, &node);
11829 if (result != ISC_R_SUCCESS)
11830 goto fail;
11831 /*
11832 * Add glue rdatasets.
11833 */
11834 for (result = dns_rdataset_first(nsrdataset);
11835 result == ISC_R_SUCCESS;
11836 result = dns_rdataset_next(nsrdataset)) {
11837 dns_rdataset_current(nsrdataset, &rdata);
11838 result = dns_rdata_tostruct(&rdata, &ns, NULL);
11839 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11840 dns_rdata_reset(&rdata);
11841 if (!dns_name_issubdomain(&ns.name, name))
11842 continue;
11843 rdataset = NULL;
11844 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
11845 &ns.name, dns_rdatatype_aaaa,
11846 dns_rdatatype_none, NULL,
11847 &rdataset);
11848 if (result == ISC_R_SUCCESS) {
11849 result = dns_db_findnode(db, &ns.name,
11850 true, &node);
11851 if (result != ISC_R_SUCCESS)
11852 goto fail;
11853 result = dns_db_addrdataset(db, node, version, 0,
11854 rdataset, 0, NULL);
11855 dns_db_detachnode(db, &node);
11856 if (result != ISC_R_SUCCESS)
11857 goto fail;
11858 }
11859 rdataset = NULL;
11860 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
11861 &ns.name, dns_rdatatype_a,
11862 dns_rdatatype_none, NULL,
11863 &rdataset);
11864 if (result == ISC_R_SUCCESS) {
11865 result = dns_db_findnode(db, &ns.name,
11866 true, &node);
11867 if (result != ISC_R_SUCCESS)
11868 goto fail;
11869 result = dns_db_addrdataset(db, node, version, 0,
11870 rdataset, 0, NULL);
11871 dns_db_detachnode(db, &node);
11872 if (result != ISC_R_SUCCESS)
11873 goto fail;
11874 }
11875 }
11876 if (result != ISC_R_NOMORE)
11877 goto fail;
11878
11879 return (ISC_R_SUCCESS);
11880
11881fail:
11882 return (result);
11883}
11884
11885static void
11886stub_callback(isc_task_t *task, isc_event_t *event) {
11887 const char me[] = "stub_callback";
11888 dns_requestevent_t *revent = (dns_requestevent_t *)event;
11889 dns_stub_t *stub = NULL;
11890 dns_message_t *msg = NULL;
11891 dns_zone_t *zone = NULL;
11892 char master[ISC_SOCKADDR_FORMATSIZE];
11893 char source[ISC_SOCKADDR_FORMATSIZE];
11894 uint32_t nscnt, cnamecnt, refresh, retry, expire;
11895 isc_result_t result;
11896 isc_time_t now;
11897 bool exiting = false;
11898 isc_interval_t i;
11899 unsigned int j, soacount;
11900
11901 stub = revent->ev_arg;
11902 INSIST(DNS_STUB_VALID(stub));
11903
11904 UNUSED(task);
11905
11906 zone = stub->zone;
11907
11908 ENTER;
11909
11910 TIME_NOW(&now);
11911
11912 LOCK_ZONE(zone);
11913
11914 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11915 zone_debuglog(zone, me, 1, "exiting");
11916 exiting = true;
11917 goto next_master;
11918 }
11919
11920 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
11921 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
11922
11923 if (revent->result != ISC_R_SUCCESS) {
11924 if (revent->result == ISC_R_TIMEDOUT &&
11925 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11926 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11927 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11928 "refreshing stub: timeout retrying "
11929 " without EDNS master %s (source %s)",
11930 master, source);
11931 goto same_master;
11932 }
11933 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
11934 &zone->sourceaddr, &now);
11935 dns_zone_log(zone, ISC_LOG_INFO,
11936 "could not refresh stub from master %s"
11937 " (source %s): %s", master, source,
11938 dns_result_totext(revent->result));
11939 goto next_master;
11940 }
11941
11942 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
11943 if (result != ISC_R_SUCCESS)
11944 goto next_master;
11945
11946 result = dns_request_getresponse(revent->request, msg, 0);
11947 if (result != ISC_R_SUCCESS)
11948 goto next_master;
11949
11950 /*
11951 * Unexpected rcode.
11952 */
11953 if (msg->rcode != dns_rcode_noerror) {
11954 char rcode[128];
11955 isc_buffer_t rb;
11956
11957 isc_buffer_init(&rb, rcode, sizeof(rcode));
11958 (void)dns_rcode_totext(msg->rcode, &rb);
11959
11960 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
11961 (msg->rcode == dns_rcode_servfail ||
11962 msg->rcode == dns_rcode_notimp ||
11963 msg->rcode == dns_rcode_formerr)) {
11964 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11965 "refreshing stub: rcode (%.*s) retrying "
11966 "without EDNS master %s (source %s)",
11967 (int)rb.used, rcode, master, source);
11968 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11969 goto same_master;
11970 }
11971
11972 dns_zone_log(zone, ISC_LOG_INFO,
11973 "refreshing stub: "
11974 "unexpected rcode (%.*s) from %s (source %s)",
11975 (int)rb.used, rcode, master, source);
11976 goto next_master;
11977 }
11978
11979 /*
11980 * We need complete messages.
11981 */
11982 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
11983 if (dns_request_usedtcp(revent->request)) {
11984 dns_zone_log(zone, ISC_LOG_INFO,
11985 "refreshing stub: truncated TCP "
11986 "response from master %s (source %s)",
11987 master, source);
11988 goto next_master;
11989 }
11990 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
11991 goto same_master;
11992 }
11993
11994 /*
11995 * If non-auth log and next master.
11996 */
11997 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
11998 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11999 "non-authoritative answer from "
12000 "master %s (source %s)", master, source);
12001 goto next_master;
12002 }
12003
12004 /*
12005 * Sanity checks.
12006 */
12007 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
12008 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
12009
12010 if (cnamecnt != 0) {
12011 dns_zone_log(zone, ISC_LOG_INFO,
12012 "refreshing stub: unexpected CNAME response "
12013 "from master %s (source %s)", master, source);
12014 goto next_master;
12015 }
12016
12017 if (nscnt == 0) {
12018 dns_zone_log(zone, ISC_LOG_INFO,
12019 "refreshing stub: no NS records in response "
12020 "from master %s (source %s)", master, source);
12021 goto next_master;
12022 }
12023
12024 /*
12025 * Save answer.
12026 */
12027 result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
12028 if (result != ISC_R_SUCCESS) {
12029 dns_zone_log(zone, ISC_LOG_INFO,
12030 "refreshing stub: unable to save NS records "
12031 "from master %s (source %s)", master, source);
12032 goto next_master;
12033 }
12034
12035 /*
12036 * Tidy up.
12037 */
12038 dns_db_closeversion(stub->db, &stub->version, true);
12039 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12040 if (zone->db == NULL)
12041 zone_attachdb(zone, stub->db);
12042 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
12043 &refresh, &retry, &expire, NULL, NULL);
12044 if (result == ISC_R_SUCCESS && soacount > 0U) {
12045 zone->refresh = RANGE(refresh, zone->minrefresh,
12046 zone->maxrefresh);
12047 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
12048 zone->expire = RANGE(expire, zone->refresh + zone->retry,
12049 DNS_MAX_EXPIRE);
12050 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
12051 }
12052 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12053 dns_db_detach(&stub->db);
12054
12055 dns_message_destroy(&msg);
12056 isc_event_free(&event);
12057 dns_request_destroy(&zone->request);
12058
12059 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12060 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
12061 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
12062 isc_interval_set(&i, zone->expire, 0);
12063 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
12064
12065 if (zone->masterfile != NULL)
12066 zone_needdump(zone, 0);
12067
12068 zone_settimer(zone, &now);
12069 goto free_stub;
12070
12071 next_master:
12072 if (stub->version != NULL)
12073 dns_db_closeversion(stub->db, &stub->version, false);
12074 if (stub->db != NULL)
12075 dns_db_detach(&stub->db);
12076 if (msg != NULL)
12077 dns_message_destroy(&msg);
12078 isc_event_free(&event);
12079 dns_request_destroy(&zone->request);
12080 /*
12081 * Skip to next failed / untried master.
12082 */
12083 do {
12084 zone->curmaster++;
12085 } while (zone->curmaster < zone->masterscnt &&
12086 zone->mastersok[zone->curmaster]);
12087 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
12088 if (exiting || zone->curmaster >= zone->masterscnt) {
12089 bool done = true;
12090 if (!exiting &&
12091 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
12092 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12093 /*
12094 * Did we get a good answer from all the masters?
12095 */
12096 for (j = 0; j < zone->masterscnt; j++)
12097 if (zone->mastersok[j] == false) {
12098 done = false;
12099 break;
12100 }
12101 } else
12102 done = true;
12103 if (!done) {
12104 zone->curmaster = 0;
12105 /*
12106 * Find the next failed master.
12107 */
12108 while (zone->curmaster < zone->masterscnt &&
12109 zone->mastersok[zone->curmaster])
12110 zone->curmaster++;
12111 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12112 } else {
12113 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12114
12115 zone_settimer(zone, &now);
12116 goto free_stub;
12117 }
12118 }
12119 queue_soa_query(zone);
12120 goto free_stub;
12121
12122 same_master:
12123 if (msg != NULL)
12124 dns_message_destroy(&msg);
12125 isc_event_free(&event);
12126 dns_request_destroy(&zone->request);
12127 ns_query(zone, NULL, stub);
12128 UNLOCK_ZONE(zone);
12129 goto done;
12130
12131 free_stub:
12132 UNLOCK_ZONE(zone);
12133 stub->magic = 0;
12134 dns_zone_idetach(&stub->zone);
12135 INSIST(stub->db == NULL);
12136 INSIST(stub->version == NULL);
12137 isc_mem_put(stub->mctx, stub, sizeof(*stub));
12138
12139 done:
12140 INSIST(event == NULL);
12141 return;
12142}
12143
12144/*
12145 * Get the EDNS EXPIRE option from the response and if it exists trim
12146 * expire to be not more than it.
12147 */
12148static void
12149get_edns_expire(dns_zone_t * zone, dns_message_t *message,
12150 uint32_t *expirep)
12151{
12152 isc_result_t result;
12153 uint32_t expire;
12154 dns_rdata_t rdata = DNS_RDATA_INIT;
12155 isc_buffer_t optbuf;
12156 uint16_t optcode;
12157 uint16_t optlen;
12158
12159 REQUIRE(expirep != NULL);
12160 REQUIRE(message != NULL);
12161
12162 if (message->opt == NULL)
12163 return;
12164
12165 result = dns_rdataset_first(message->opt);
12166 if (result == ISC_R_SUCCESS) {
12167 dns_rdataset_current(message->opt, &rdata);
12168 isc_buffer_init(&optbuf, rdata.data, rdata.length);
12169 isc_buffer_add(&optbuf, rdata.length);
12170 while (isc_buffer_remaininglength(&optbuf) >= 4) {
12171 optcode = isc_buffer_getuint16(&optbuf);
12172 optlen = isc_buffer_getuint16(&optbuf);
12173 /*
12174 * A EDNS EXPIRE response has a length of 4.
12175 */
12176 if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
12177 isc_buffer_forward(&optbuf, optlen);
12178 continue;
12179 }
12180 expire = isc_buffer_getuint32(&optbuf);
12181 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12182 "got EDNS EXPIRE of %u", expire);
12183 /*
12184 * Trim *expirep?
12185 */
12186 if (expire < *expirep)
12187 *expirep = expire;
12188 break;
12189 }
12190 }
12191}
12192
12193/*
12194 * Set the file modification time zone->expire seconds before expiretime.
12195 */
12196static void
12197setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
12198 isc_result_t result;
12199 isc_time_t when;
12200 isc_interval_t i;
12201
12202 isc_interval_set(&i, zone->expire, 0);
12203 result = isc_time_subtract(expiretime, &i, &when);
12204 if (result != ISC_R_SUCCESS)
12205 return;
12206
12207 result = ISC_R_FAILURE;
12208 if (zone->journal != NULL)
12209 result = isc_file_settime(zone->journal, &when);
12210 if (result == ISC_R_SUCCESS &&
12211 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12212 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
12213 result = isc_file_settime(zone->masterfile, &when);
12214 else if (result != ISC_R_SUCCESS)
12215 result = isc_file_settime(zone->masterfile, &when);
12216
12217 /*
12218 * Someone removed the file from underneath us!
12219 */
12220 if (result == ISC_R_FILENOTFOUND) {
12221 zone_needdump(zone, DNS_DUMP_DELAY);
12222 } else if (result != ISC_R_SUCCESS)
12223 dns_zone_log(zone, ISC_LOG_ERROR, "refresh: could not set "
12224 "file modification time of '%s': %s",
12225 zone->masterfile, dns_result_totext(result));
12226}
12227
12228/*
12229 * An SOA query has finished (successfully or not).
12230 */
12231static void
12232refresh_callback(isc_task_t *task, isc_event_t *event) {
12233 const char me[] = "refresh_callback";
12234 dns_requestevent_t *revent = (dns_requestevent_t *)event;
12235 dns_zone_t *zone;
12236 dns_message_t *msg = NULL;
12237 uint32_t soacnt, cnamecnt, soacount, nscount;
12238 isc_time_t now;
12239 char master[ISC_SOCKADDR_FORMATSIZE];
12240 char source[ISC_SOCKADDR_FORMATSIZE];
12241 dns_rdataset_t *rdataset = NULL;
12242 dns_rdata_t rdata = DNS_RDATA_INIT;
12243 dns_rdata_soa_t soa;
12244 isc_result_t result;
12245 uint32_t serial, oldserial = 0;
12246 unsigned int j;
12247 bool do_queue_xfrin = false;
12248
12249 zone = revent->ev_arg;
12250 INSIST(DNS_ZONE_VALID(zone));
12251
12252 UNUSED(task);
12253
12254 ENTER;
12255
12256 TIME_NOW(&now);
12257
12258 LOCK_ZONE(zone);
12259
12260 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12261 isc_event_free(&event);
12262 dns_request_destroy(&zone->request);
12263 goto detach;
12264 }
12265
12266 /*
12267 * if timeout log and next master;
12268 */
12269
12270 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12271 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12272
12273 if (revent->result != ISC_R_SUCCESS) {
12274 if (revent->result == ISC_R_TIMEDOUT &&
12275 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12276 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12277 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12278 "refresh: timeout retrying without EDNS "
12279 "master %s (source %s)", master, source);
12280 goto same_master;
12281 }
12282 if (revent->result == ISC_R_TIMEDOUT &&
12283 !dns_request_usedtcp(revent->request)) {
12284 dns_zone_log(zone, ISC_LOG_INFO,
12285 "refresh: retry limit for "
12286 "master %s exceeded (source %s)",
12287 master, source);
12288 /* Try with slave with TCP. */
12289 if ((zone->type == dns_zone_slave ||
12290 zone->type == dns_zone_mirror ||
12291 zone->type == dns_zone_redirect) &&
12292 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
12293 {
12294 if (!dns_zonemgr_unreachable(zone->zmgr,
12295 &zone->masteraddr,
12296 &zone->sourceaddr,
12297 &now))
12298 {
12299 DNS_ZONE_SETFLAG(zone,
12300 DNS_ZONEFLG_SOABEFOREAXFR);
12301 goto tcp_transfer;
12302 }
12303 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12304 "refresh: skipped tcp fallback "
12305 "as master %s (source %s) is "
12306 "unreachable (cached)",
12307 master, source);
12308 }
12309 } else
12310 dns_zone_log(zone, ISC_LOG_INFO,
12311 "refresh: failure trying master "
12312 "%s (source %s): %s", master, source,
12313 dns_result_totext(revent->result));
12314 goto next_master;
12315 }
12316
12317 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12318 if (result != ISC_R_SUCCESS)
12319 goto next_master;
12320 result = dns_request_getresponse(revent->request, msg, 0);
12321 if (result != ISC_R_SUCCESS) {
12322 dns_zone_log(zone, ISC_LOG_INFO,
12323 "refresh: failure trying master "
12324 "%s (source %s): %s", master, source,
12325 dns_result_totext(result));
12326 goto next_master;
12327 }
12328
12329 /*
12330 * Unexpected rcode.
12331 */
12332 if (msg->rcode != dns_rcode_noerror) {
12333 char rcode[128];
12334 isc_buffer_t rb;
12335
12336 isc_buffer_init(&rb, rcode, sizeof(rcode));
12337 (void)dns_rcode_totext(msg->rcode, &rb);
12338
12339 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
12340 (msg->rcode == dns_rcode_servfail ||
12341 msg->rcode == dns_rcode_notimp ||
12342 msg->rcode == dns_rcode_formerr)) {
12343 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12344 "refresh: rcode (%.*s) retrying without "
12345 "EDNS master %s (source %s)",
12346 (int)rb.used, rcode, master, source);
12347 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12348 goto same_master;
12349 }
12350 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
12351 msg->rcode == dns_rcode_badvers) {
12352 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12353 "refresh: rcode (%.*s) retrying without "
12354 "EDNS EXPIRE OPTION master %s (source %s)",
12355 (int)rb.used, rcode, master, source);
12356 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12357 goto same_master;
12358 }
12359 dns_zone_log(zone, ISC_LOG_INFO,
12360 "refresh: unexpected rcode (%.*s) from "
12361 "master %s (source %s)", (int)rb.used, rcode,
12362 master, source);
12363 /*
12364 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
12365 */
12366 if (msg->rcode == dns_rcode_refused &&
12367 (zone->type == dns_zone_slave ||
12368 zone->type == dns_zone_mirror ||
12369 zone->type == dns_zone_redirect))
12370 {
12371 goto tcp_transfer;
12372 }
12373 goto next_master;
12374 }
12375
12376 /*
12377 * If truncated punt to zone transfer which will query again.
12378 */
12379 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
12380 if (zone->type == dns_zone_slave ||
12381 zone->type == dns_zone_mirror ||
12382 zone->type == dns_zone_redirect)
12383 {
12384 dns_zone_log(zone, ISC_LOG_INFO,
12385 "refresh: truncated UDP answer, "
12386 "initiating TCP zone xfer "
12387 "for master %s (source %s)",
12388 master, source);
12389 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
12390 goto tcp_transfer;
12391 } else {
12392 INSIST(zone->type == dns_zone_stub);
12393 if (dns_request_usedtcp(revent->request)) {
12394 dns_zone_log(zone, ISC_LOG_INFO,
12395 "refresh: truncated TCP response "
12396 "from master %s (source %s)",
12397 master, source);
12398 goto next_master;
12399 }
12400 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
12401 goto same_master;
12402 }
12403 }
12404
12405 /*
12406 * if non-auth log and next master;
12407 */
12408 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
12409 dns_zone_log(zone, ISC_LOG_INFO,
12410 "refresh: non-authoritative answer from "
12411 "master %s (source %s)", master, source);
12412 goto next_master;
12413 }
12414
12415 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
12416 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
12417 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
12418 soacount = message_count(msg, DNS_SECTION_AUTHORITY,
12419 dns_rdatatype_soa);
12420
12421 /*
12422 * There should not be a CNAME record at top of zone.
12423 */
12424 if (cnamecnt != 0) {
12425 dns_zone_log(zone, ISC_LOG_INFO,
12426 "refresh: CNAME at top of zone "
12427 "in master %s (source %s)", master, source);
12428 goto next_master;
12429 }
12430
12431 /*
12432 * if referral log and next master;
12433 */
12434 if (soacnt == 0 && soacount == 0 && nscount != 0) {
12435 dns_zone_log(zone, ISC_LOG_INFO,
12436 "refresh: referral response "
12437 "from master %s (source %s)", master, source);
12438 goto next_master;
12439 }
12440
12441 /*
12442 * if nodata log and next master;
12443 */
12444 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
12445 dns_zone_log(zone, ISC_LOG_INFO,
12446 "refresh: NODATA response "
12447 "from master %s (source %s)", master, source);
12448 goto next_master;
12449 }
12450
12451 /*
12452 * Only one soa at top of zone.
12453 */
12454 if (soacnt != 1) {
12455 dns_zone_log(zone, ISC_LOG_INFO,
12456 "refresh: answer SOA count (%d) != 1 "
12457 "from master %s (source %s)",
12458 soacnt, master, source);
12459 goto next_master;
12460 }
12461
12462 /*
12463 * Extract serial
12464 */
12465 rdataset = NULL;
12466 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
12467 dns_rdatatype_soa, dns_rdatatype_none,
12468 NULL, &rdataset);
12469 if (result != ISC_R_SUCCESS) {
12470 dns_zone_log(zone, ISC_LOG_INFO,
12471 "refresh: unable to get SOA record "
12472 "from master %s (source %s)", master, source);
12473 goto next_master;
12474 }
12475
12476 result = dns_rdataset_first(rdataset);
12477 if (result != ISC_R_SUCCESS) {
12478 dns_zone_log(zone, ISC_LOG_INFO,
12479 "refresh: dns_rdataset_first() failed");
12480 goto next_master;
12481 }
12482
12483 dns_rdataset_current(rdataset, &rdata);
12484 result = dns_rdata_tostruct(&rdata, &soa, NULL);
12485 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12486
12487 serial = soa.serial;
12488 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
12489 unsigned int dbsoacount;
12490 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
12491 &oldserial, NULL, NULL, NULL, NULL,
12492 NULL);
12493 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12494 RUNTIME_CHECK(dbsoacount > 0U);
12495 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
12496 serial, oldserial);
12497 } else
12498 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
12499 serial);
12500
12501 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
12502 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
12503 isc_serial_gt(serial, oldserial)) {
12504 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
12505 &zone->sourceaddr, &now))
12506 {
12507 dns_zone_log(zone, ISC_LOG_INFO,
12508 "refresh: skipping %s as master %s "
12509 "(source %s) is unreachable (cached)",
12510 (zone->type == dns_zone_slave ||
12511 zone->type == dns_zone_mirror ||
12512 zone->type == dns_zone_redirect) ?
12513 "zone transfer" : "NS query",
12514 master, source);
12515 goto next_master;
12516 }
12517 tcp_transfer:
12518 isc_event_free(&event);
12519 dns_request_destroy(&zone->request);
12520 if (zone->type == dns_zone_slave ||
12521 zone->type == dns_zone_mirror ||
12522 zone->type == dns_zone_redirect)
12523 {
12524 do_queue_xfrin = true;
12525 } else {
12526 INSIST(zone->type == dns_zone_stub);
12527 ns_query(zone, rdataset, NULL);
12528 }
12529 if (msg != NULL)
12530 dns_message_destroy(&msg);
12531 } else if (isc_serial_eq(soa.serial, oldserial)) {
12532 isc_time_t expiretime;
12533 uint32_t expire;
12534
12535 /*
12536 * Compute the new expire time based on this response.
12537 */
12538 expire = zone->expire;
12539 get_edns_expire(zone, msg, &expire);
12540 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
12541
12542 /*
12543 * Has the expire time improved?
12544 */
12545 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
12546 zone->expiretime = expiretime;
12547 if (zone->masterfile != NULL)
12548 setmodtime(zone, &expiretime);
12549 }
12550
12551 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
12552 zone->mastersok[zone->curmaster] = true;
12553 goto next_master;
12554 } else {
12555 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
12556 dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
12557 "received from master %s < ours (%u)",
12558 soa.serial, master, oldserial);
12559 else
12560 zone_debuglog(zone, me, 1, "ahead");
12561 zone->mastersok[zone->curmaster] = true;
12562 goto next_master;
12563 }
12564 if (msg != NULL)
12565 dns_message_destroy(&msg);
12566 goto detach;
12567
12568 next_master:
12569 if (msg != NULL)
12570 dns_message_destroy(&msg);
12571 isc_event_free(&event);
12572 dns_request_destroy(&zone->request);
12573 /*
12574 * Skip to next failed / untried master.
12575 */
12576 do {
12577 zone->curmaster++;
12578 } while (zone->curmaster < zone->masterscnt &&
12579 zone->mastersok[zone->curmaster]);
12580 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
12581 if (zone->curmaster >= zone->masterscnt) {
12582 bool done = true;
12583 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
12584 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12585 /*
12586 * Did we get a good answer from all the masters?
12587 */
12588 for (j = 0; j < zone->masterscnt; j++)
12589 if (zone->mastersok[j] == false) {
12590 done = false;
12591 break;
12592 }
12593 } else
12594 done = true;
12595 if (!done) {
12596 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12597 zone->curmaster = 0;
12598 /*
12599 * Find the next failed master.
12600 */
12601 while (zone->curmaster < zone->masterscnt &&
12602 zone->mastersok[zone->curmaster])
12603 zone->curmaster++;
12604 goto requeue;
12605 }
12606 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12607 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
12608 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12609 zone->refreshtime = now;
12610 }
12611 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12612 zone_settimer(zone, &now);
12613 goto detach;
12614 }
12615
12616 requeue:
12617 queue_soa_query(zone);
12618 goto detach;
12619
12620 same_master:
12621 if (msg != NULL)
12622 dns_message_destroy(&msg);
12623 isc_event_free(&event);
12624 dns_request_destroy(&zone->request);
12625 queue_soa_query(zone);
12626
12627 detach:
12628 UNLOCK_ZONE(zone);
12629 if (do_queue_xfrin)
12630 queue_xfrin(zone);
12631 dns_zone_idetach(&zone);
12632 return;
12633}
12634
12635static void
12636queue_soa_query(dns_zone_t *zone) {
12637 const char me[] = "queue_soa_query";
12638 isc_event_t *e;
12639 dns_zone_t *dummy = NULL;
12640 isc_result_t result;
12641
12642 ENTER;
12643 /*
12644 * Locked by caller
12645 */
12646 REQUIRE(LOCKED_ZONE(zone));
12647
12648 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12649 cancel_refresh(zone);
12650 return;
12651 }
12652
12653 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
12654 soa_query, zone, sizeof(isc_event_t));
12655 if (e == NULL) {
12656 cancel_refresh(zone);
12657 return;
12658 }
12659
12660 /*
12661 * Attach so that we won't clean up
12662 * until the event is delivered.
12663 */
12664 zone_iattach(zone, &dummy);
12665
12666 e->ev_arg = zone;
12667 e->ev_sender = NULL;
12668 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
12669 if (result != ISC_R_SUCCESS) {
12670 zone_idetach(&dummy);
12671 isc_event_free(&e);
12672 cancel_refresh(zone);
12673 }
12674}
12675
12676static inline isc_result_t
12677create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
12678 dns_message_t **messagep)
12679{
12680 dns_message_t *message = NULL;
12681 dns_name_t *qname = NULL;
12682 dns_rdataset_t *qrdataset = NULL;
12683 isc_result_t result;
12684
12685 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
12686 &message);
12687 if (result != ISC_R_SUCCESS)
12688 goto cleanup;
12689
12690 message->opcode = dns_opcode_query;
12691 message->rdclass = zone->rdclass;
12692
12693 result = dns_message_gettempname(message, &qname);
12694 if (result != ISC_R_SUCCESS)
12695 goto cleanup;
12696
12697 result = dns_message_gettemprdataset(message, &qrdataset);
12698 if (result != ISC_R_SUCCESS)
12699 goto cleanup;
12700
12701 /*
12702 * Make question.
12703 */
12704 dns_name_init(qname, NULL);
12705 dns_name_clone(&zone->origin, qname);
12706 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
12707 ISC_LIST_APPEND(qname->list, qrdataset, link);
12708 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
12709
12710 *messagep = message;
12711 return (ISC_R_SUCCESS);
12712
12713 cleanup:
12714 if (qname != NULL)
12715 dns_message_puttempname(message, &qname);
12716 if (qrdataset != NULL)
12717 dns_message_puttemprdataset(message, &qrdataset);
12718 if (message != NULL)
12719 dns_message_destroy(&message);
12720 return (result);
12721}
12722
12723static isc_result_t
12724add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
12725 bool reqexpire)
12726{
12727 isc_result_t result;
12728 dns_rdataset_t *rdataset = NULL;
12729 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
12730 int count = 0;
12731
12732 /* Set EDNS options if applicable */
12733 if (reqnsid) {
12734 INSIST(count < DNS_EDNSOPTIONS);
12735 ednsopts[count].code = DNS_OPT_NSID;
12736 ednsopts[count].length = 0;
12737 ednsopts[count].value = NULL;
12738 count++;
12739 }
12740 if (reqexpire) {
12741 INSIST(count < DNS_EDNSOPTIONS);
12742 ednsopts[count].code = DNS_OPT_EXPIRE;
12743 ednsopts[count].length = 0;
12744 ednsopts[count].value = NULL;
12745 count++;
12746 }
12747 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
12748 ednsopts, count);
12749 if (result != ISC_R_SUCCESS)
12750 return (result);
12751
12752 return (dns_message_setopt(message, rdataset));
12753}
12754
12755static void
12756soa_query(isc_task_t *task, isc_event_t *event) {
12757 const char me[] = "soa_query";
12758 isc_result_t result = ISC_R_FAILURE;
12759 dns_message_t *message = NULL;
12760 dns_zone_t *zone = event->ev_arg;
12761 dns_zone_t *dummy = NULL;
12762 isc_netaddr_t masterip;
12763 dns_tsigkey_t *key = NULL;
12764 uint32_t options;
12765 bool cancel = true;
12766 int timeout;
12767 bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
12768 uint16_t udpsize = SEND_BUFFER_SIZE;
12769 isc_dscp_t dscp = -1;
12770
12771 REQUIRE(DNS_ZONE_VALID(zone));
12772
12773 UNUSED(task);
12774
12775 ENTER;
12776
12777 LOCK_ZONE(zone);
12778 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
12779 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12780 zone->view->requestmgr == NULL) {
12781 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12782 cancel = false;
12783 goto cleanup;
12784 }
12785
12786 again:
12787 result = create_query(zone, dns_rdatatype_soa, &message);
12788 if (result != ISC_R_SUCCESS)
12789 goto cleanup;
12790
12791 INSIST(zone->masterscnt > 0);
12792 INSIST(zone->curmaster < zone->masterscnt);
12793
12794 zone->masteraddr = zone->masters[zone->curmaster];
12795
12796 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12797 /*
12798 * First, look for a tsig key in the master statement, then
12799 * try for a server key.
12800 */
12801 if ((zone->masterkeynames != NULL) &&
12802 (zone->masterkeynames[zone->curmaster] != NULL)) {
12803 dns_view_t *view = dns_zone_getview(zone);
12804 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12805 result = dns_view_gettsig(view, keyname, &key);
12806 if (result != ISC_R_SUCCESS) {
12807 char namebuf[DNS_NAME_FORMATSIZE];
12808 dns_name_format(keyname, namebuf, sizeof(namebuf));
12809 dns_zone_log(zone, ISC_LOG_ERROR,
12810 "unable to find key: %s", namebuf);
12811 goto skip_master;
12812 }
12813 }
12814 if (key == NULL) {
12815 result = dns_view_getpeertsig(zone->view, &masterip, &key);
12816 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12817 char addrbuf[ISC_NETADDR_FORMATSIZE];
12818 isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
12819 dns_zone_log(zone, ISC_LOG_ERROR,
12820 "unable to find TSIG key for %s", addrbuf);
12821 goto skip_master;
12822 }
12823 }
12824
12825 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
12826 DNS_REQUESTOPT_TCP : 0;
12827 have_xfrsource = have_xfrdscp = false;
12828 reqnsid = zone->view->requestnsid;
12829 reqexpire = zone->requestexpire;
12830 if (zone->view->peers != NULL) {
12831 dns_peer_t *peer = NULL;
12832 bool edns, usetcp;
12833 result = dns_peerlist_peerbyaddr(zone->view->peers,
12834 &masterip, &peer);
12835 if (result == ISC_R_SUCCESS) {
12836 result = dns_peer_getsupportedns(peer, &edns);
12837 if (result == ISC_R_SUCCESS && !edns)
12838 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12839 result = dns_peer_gettransfersource(peer,
12840 &zone->sourceaddr);
12841 if (result == ISC_R_SUCCESS)
12842 have_xfrsource = true;
12843 (void)dns_peer_gettransferdscp(peer, &dscp);
12844 if (dscp != -1)
12845 have_xfrdscp = true;
12846 if (zone->view->resolver != NULL)
12847 udpsize =
12848 dns_resolver_getudpsize(zone->view->resolver);
12849 (void)dns_peer_getudpsize(peer, &udpsize);
12850 (void)dns_peer_getrequestnsid(peer, &reqnsid);
12851 (void)dns_peer_getrequestexpire(peer, &reqexpire);
12852 result = dns_peer_getforcetcp(peer, &usetcp);
12853 if (result == ISC_R_SUCCESS && usetcp)
12854 options |= DNS_REQUESTOPT_TCP;
12855 }
12856 }
12857
12858 switch (isc_sockaddr_pf(&zone->masteraddr)) {
12859 case PF_INET:
12860 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12861 if (isc_sockaddr_equal(&zone->altxfrsource4,
12862 &zone->xfrsource4))
12863 goto skip_master;
12864 zone->sourceaddr = zone->altxfrsource4;
12865 if (!have_xfrdscp)
12866 dscp = zone->altxfrsource4dscp;
12867 } else if (!have_xfrsource) {
12868 zone->sourceaddr = zone->xfrsource4;
12869 if (!have_xfrdscp)
12870 dscp = zone->xfrsource4dscp;
12871 }
12872 break;
12873 case PF_INET6:
12874 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12875 if (isc_sockaddr_equal(&zone->altxfrsource6,
12876 &zone->xfrsource6))
12877 goto skip_master;
12878 zone->sourceaddr = zone->altxfrsource6;
12879 if (!have_xfrdscp)
12880 dscp = zone->altxfrsource6dscp;
12881 } else if (!have_xfrsource) {
12882 zone->sourceaddr = zone->xfrsource6;
12883 if (!have_xfrdscp)
12884 dscp = zone->xfrsource6dscp;
12885 }
12886 break;
12887 default:
12888 result = ISC_R_NOTIMPLEMENTED;
12889 goto cleanup;
12890 }
12891
12892 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12893 result = add_opt(message, udpsize, reqnsid, reqexpire);
12894 if (result != ISC_R_SUCCESS)
12895 zone_debuglog(zone, me, 1,
12896 "unable to add opt record: %s",
12897 dns_result_totext(result));
12898 }
12899
12900 zone_iattach(zone, &dummy);
12901 timeout = 15;
12902 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
12903 timeout = 30;
12904 result = dns_request_createvia(zone->view->requestmgr, message,
12905 &zone->sourceaddr, &zone->masteraddr,
12906 dscp, options, key, timeout * 3,
12907 timeout, 0, zone->task,
12908 refresh_callback, zone, &zone->request);
12909 if (result != ISC_R_SUCCESS) {
12910 zone_idetach(&dummy);
12911 zone_debuglog(zone, me, 1,
12912 "dns_request_createvia4() failed: %s",
12913 dns_result_totext(result));
12914 goto skip_master;
12915 } else {
12916 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
12917 inc_stats(zone, dns_zonestatscounter_soaoutv4);
12918 else
12919 inc_stats(zone, dns_zonestatscounter_soaoutv6);
12920 }
12921 cancel = false;
12922
12923 cleanup:
12924 if (key != NULL)
12925 dns_tsigkey_detach(&key);
12926 if (result != ISC_R_SUCCESS)
12927 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12928 if (message != NULL)
12929 dns_message_destroy(&message);
12930 if (cancel)
12931 cancel_refresh(zone);
12932 isc_event_free(&event);
12933 UNLOCK_ZONE(zone);
12934 dns_zone_idetach(&zone);
12935 return;
12936
12937 skip_master:
12938 if (key != NULL)
12939 dns_tsigkey_detach(&key);
12940 dns_message_destroy(&message);
12941 /*
12942 * Skip to next failed / untried master.
12943 */
12944 do {
12945 zone->curmaster++;
12946 } while (zone->curmaster < zone->masterscnt &&
12947 zone->mastersok[zone->curmaster]);
12948 if (zone->curmaster < zone->masterscnt)
12949 goto again;
12950 zone->curmaster = 0;
12951 goto cleanup;
12952}
12953
12954static void
12955ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
12956 const char me[] = "ns_query";
12957 isc_result_t result;
12958 dns_message_t *message = NULL;
12959 isc_netaddr_t masterip;
12960 dns_tsigkey_t *key = NULL;
12961 dns_dbnode_t *node = NULL;
12962 int timeout;
12963 bool have_xfrsource = false, have_xfrdscp = false;
12964 bool reqnsid;
12965 uint16_t udpsize = SEND_BUFFER_SIZE;
12966 isc_dscp_t dscp = -1;
12967
12968 REQUIRE(DNS_ZONE_VALID(zone));
12969 REQUIRE(LOCKED_ZONE(zone));
12970 REQUIRE((soardataset != NULL && stub == NULL) ||
12971 (soardataset == NULL && stub != NULL));
12972 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
12973
12974 ENTER;
12975
12976 if (stub == NULL) {
12977 stub = isc_mem_get(zone->mctx, sizeof(*stub));
12978 if (stub == NULL)
12979 goto cleanup;
12980 stub->magic = STUB_MAGIC;
12981 stub->mctx = zone->mctx;
12982 stub->zone = NULL;
12983 stub->db = NULL;
12984 stub->version = NULL;
12985
12986 /*
12987 * Attach so that the zone won't disappear from under us.
12988 */
12989 zone_iattach(zone, &stub->zone);
12990
12991 /*
12992 * If a db exists we will update it, otherwise we create a
12993 * new one and attach it to the zone once we have the NS
12994 * RRset and glue.
12995 */
12996 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12997 if (zone->db != NULL) {
12998 dns_db_attach(zone->db, &stub->db);
12999 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13000 } else {
13001 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13002
13003 INSIST(zone->db_argc >= 1);
13004 result = dns_db_create(zone->mctx, zone->db_argv[0],
13005 &zone->origin, dns_dbtype_stub,
13006 zone->rdclass,
13007 zone->db_argc - 1,
13008 zone->db_argv + 1,
13009 &stub->db);
13010 if (result != ISC_R_SUCCESS) {
13011 dns_zone_log(zone, ISC_LOG_ERROR,
13012 "refreshing stub: "
13013 "could not create "
13014 "database: %s",
13015 dns_result_totext(result));
13016 goto cleanup;
13017 }
13018 dns_db_settask(stub->db, zone->task);
13019 }
13020
13021 result = dns_db_newversion(stub->db, &stub->version);
13022 if (result != ISC_R_SUCCESS) {
13023 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
13024 "dns_db_newversion() failed: %s",
13025 dns_result_totext(result));
13026 goto cleanup;
13027 }
13028
13029 /*
13030 * Update SOA record.
13031 */
13032 result = dns_db_findnode(stub->db, &zone->origin, true,
13033 &node);
13034 if (result != ISC_R_SUCCESS) {
13035 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
13036 "dns_db_findnode() failed: %s",
13037 dns_result_totext(result));
13038 goto cleanup;
13039 }
13040
13041 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
13042 soardataset, 0, NULL);
13043 dns_db_detachnode(stub->db, &node);
13044 if (result != ISC_R_SUCCESS) {
13045 dns_zone_log(zone, ISC_LOG_INFO,
13046 "refreshing stub: "
13047 "dns_db_addrdataset() failed: %s",
13048 dns_result_totext(result));
13049 goto cleanup;
13050 }
13051 }
13052
13053 /*
13054 * XXX Optimisation: Create message when zone is setup and reuse.
13055 */
13056 result = create_query(zone, dns_rdatatype_ns, &message);
13057 INSIST(result == ISC_R_SUCCESS);
13058
13059 INSIST(zone->masterscnt > 0);
13060 INSIST(zone->curmaster < zone->masterscnt);
13061 zone->masteraddr = zone->masters[zone->curmaster];
13062
13063 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
13064 /*
13065 * First, look for a tsig key in the master statement, then
13066 * try for a server key.
13067 */
13068 if ((zone->masterkeynames != NULL) &&
13069 (zone->masterkeynames[zone->curmaster] != NULL)) {
13070 dns_view_t *view = dns_zone_getview(zone);
13071 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
13072 result = dns_view_gettsig(view, keyname, &key);
13073 if (result != ISC_R_SUCCESS) {
13074 char namebuf[DNS_NAME_FORMATSIZE];
13075 dns_name_format(keyname, namebuf, sizeof(namebuf));
13076 dns_zone_log(zone, ISC_LOG_ERROR,
13077 "unable to find key: %s", namebuf);
13078 }
13079 }
13080 if (key == NULL)
13081 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
13082
13083 reqnsid = zone->view->requestnsid;
13084 if (zone->view->peers != NULL) {
13085 dns_peer_t *peer = NULL;
13086 bool edns;
13087 result = dns_peerlist_peerbyaddr(zone->view->peers,
13088 &masterip, &peer);
13089 if (result == ISC_R_SUCCESS) {
13090 result = dns_peer_getsupportedns(peer, &edns);
13091 if (result == ISC_R_SUCCESS && !edns)
13092 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13093 result = dns_peer_gettransfersource(peer,
13094 &zone->sourceaddr);
13095 if (result == ISC_R_SUCCESS)
13096 have_xfrsource = true;
13097 result = dns_peer_gettransferdscp(peer, &dscp);
13098 if (result == ISC_R_SUCCESS && dscp != -1)
13099 have_xfrdscp = true;
13100 if (zone->view->resolver != NULL)
13101 udpsize =
13102 dns_resolver_getudpsize(zone->view->resolver);
13103 (void)dns_peer_getudpsize(peer, &udpsize);
13104 (void)dns_peer_getrequestnsid(peer, &reqnsid);
13105 }
13106
13107 }
13108 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13109 result = add_opt(message, udpsize, reqnsid, false);
13110 if (result != ISC_R_SUCCESS)
13111 zone_debuglog(zone, me, 1,
13112 "unable to add opt record: %s",
13113 dns_result_totext(result));
13114 }
13115
13116 /*
13117 * Always use TCP so that we shouldn't truncate in additional section.
13118 */
13119 switch (isc_sockaddr_pf(&zone->masteraddr)) {
13120 case PF_INET:
13121 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13122 zone->sourceaddr = zone->altxfrsource4;
13123 if (!have_xfrdscp)
13124 dscp = zone->altxfrsource4dscp;
13125 } else if (!have_xfrsource) {
13126 zone->sourceaddr = zone->xfrsource4;
13127 if (!have_xfrdscp)
13128 dscp = zone->xfrsource4dscp;
13129 }
13130 break;
13131 case PF_INET6:
13132 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13133 zone->sourceaddr = zone->altxfrsource6;
13134 if (!have_xfrdscp)
13135 dscp = zone->altxfrsource6dscp;
13136 } else if (!have_xfrsource) {
13137 zone->sourceaddr = zone->xfrsource6;
13138 if (!have_xfrdscp)
13139 dscp = zone->xfrsource6dscp;
13140 }
13141 break;
13142 default:
13143 result = ISC_R_NOTIMPLEMENTED;
13144 POST(result);
13145 goto cleanup;
13146 }
13147 timeout = 15;
13148 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13149 timeout = 30;
13150 result = dns_request_createvia(zone->view->requestmgr, message,
13151 &zone->sourceaddr, &zone->masteraddr,
13152 dscp, DNS_REQUESTOPT_TCP, key,
13153 timeout * 3, timeout, 0, zone->task,
13154 stub_callback, stub, &zone->request);
13155 if (result != ISC_R_SUCCESS) {
13156 zone_debuglog(zone, me, 1,
13157 "dns_request_createvia() failed: %s",
13158 dns_result_totext(result));
13159 goto cleanup;
13160 }
13161 dns_message_destroy(&message);
13162 goto unlock;
13163
13164 cleanup:
13165 cancel_refresh(zone);
13166 if (stub != NULL) {
13167 stub->magic = 0;
13168 if (stub->version != NULL)
13169 dns_db_closeversion(stub->db, &stub->version,
13170 false);
13171 if (stub->db != NULL)
13172 dns_db_detach(&stub->db);
13173 if (stub->zone != NULL)
13174 zone_idetach(&stub->zone);
13175 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13176 }
13177 if (message != NULL)
13178 dns_message_destroy(&message);
13179 unlock:
13180 if (key != NULL)
13181 dns_tsigkey_detach(&key);
13182 return;
13183}
13184
13185/*
13186 * Handle the control event. Note that although this event causes the zone
13187 * to shut down, it is not a shutdown event in the sense of the task library.
13188 */
13189static void
13190zone_shutdown(isc_task_t *task, isc_event_t *event) {
13191 dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
13192 bool free_needed, linked = false;
13193 dns_zone_t *raw = NULL, *secure = NULL;
13194
13195 UNUSED(task);
13196 REQUIRE(DNS_ZONE_VALID(zone));
13197 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
13198 INSIST(isc_refcount_current(&zone->erefs) == 0);
13199
13200 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
13201
13202 /*
13203 * Stop things being restarted after we cancel them below.
13204 */
13205 LOCK_ZONE(zone);
13206 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
13207 UNLOCK_ZONE(zone);
13208
13209 /*
13210 * If we were waiting for xfrin quota, step out of
13211 * the queue.
13212 * If there's no zone manager, we can't be waiting for the
13213 * xfrin quota
13214 */
13215 if (zone->zmgr != NULL) {
13216 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13217 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
13218 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
13219 statelink);
13220 linked = true;
13221 zone->statelist = NULL;
13222 }
13223 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
13224 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
13225 statelink);
13226 zone->statelist = NULL;
13227 zmgr_resume_xfrs(zone->zmgr, false);
13228 }
13229 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13230 }
13231
13232 /*
13233 * In task context, no locking required. See zone_xfrdone().
13234 */
13235 if (zone->xfr != NULL)
13236 dns_xfrin_shutdown(zone->xfr);
13237
13238 /* Safe to release the zone now */
13239 if (zone->zmgr != NULL)
13240 dns_zonemgr_releasezone(zone->zmgr, zone);
13241
13242 LOCK_ZONE(zone);
13243 INSIST(zone != zone->raw);
13244 if (linked) {
13245 INSIST(zone->irefs > 0);
13246 zone->irefs--;
13247 }
13248 if (zone->request != NULL) {
13249 dns_request_cancel(zone->request);
13250 }
13251
13252 if (zone->readio != NULL)
13253 zonemgr_cancelio(zone->readio);
13254
13255 if (zone->lctx != NULL)
13256 dns_loadctx_cancel(zone->lctx);
13257
13258 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
13259 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13260 if (zone->writeio != NULL)
13261 zonemgr_cancelio(zone->writeio);
13262
13263 if (zone->dctx != NULL)
13264 dns_dumpctx_cancel(zone->dctx);
13265 }
13266
13267 notify_cancel(zone);
13268
13269 forward_cancel(zone);
13270
13271 if (zone->timer != NULL) {
13272 isc_timer_detach(&zone->timer);
13273 INSIST(zone->irefs > 0);
13274 zone->irefs--;
13275 }
13276
13277 /*
13278 * We have now canceled everything set the flag to allow exit_check()
13279 * to succeed. We must not unlock between setting this flag and
13280 * calling exit_check().
13281 */
13282 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
13283 free_needed = exit_check(zone);
13284 if (inline_secure(zone)) {
13285 raw = zone->raw;
13286 zone->raw = NULL;
13287 }
13288 if (inline_raw(zone)) {
13289 secure = zone->secure;
13290 zone->secure = NULL;
13291 }
13292 UNLOCK_ZONE(zone);
13293 if (raw != NULL)
13294 dns_zone_detach(&raw);
13295 if (secure != NULL)
13296 dns_zone_idetach(&secure);
13297 if (free_needed)
13298 zone_free(zone);
13299}
13300
13301static void
13302zone_timer(isc_task_t *task, isc_event_t *event) {
13303 const char me[] = "zone_timer";
13304 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
13305
13306 UNUSED(task);
13307 REQUIRE(DNS_ZONE_VALID(zone));
13308
13309 ENTER;
13310
13311 zone_maintenance(zone);
13312
13313 isc_event_free(&event);
13314}
13315
13316static void
13317zone_settimer(dns_zone_t *zone, isc_time_t *now) {
13318 const char me[] = "zone_settimer";
13319 isc_time_t next;
13320 isc_result_t result;
13321
13322 REQUIRE(DNS_ZONE_VALID(zone));
13323 ENTER;
13324
13325 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
13326 return;
13327
13328 isc_time_settoepoch(&next);
13329
13330 switch (zone->type) {
13331 case dns_zone_redirect:
13332 if (zone->masters != NULL)
13333 goto treat_as_slave;
13334 /* FALLTHROUGH */
13335
13336 case dns_zone_master:
13337 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
13338 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
13339 next = zone->notifytime;
13340 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13341 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13342 INSIST(!isc_time_isepoch(&zone->dumptime));
13343 if (isc_time_isepoch(&next) ||
13344 isc_time_compare(&zone->dumptime, &next) < 0)
13345 next = zone->dumptime;
13346 }
13347 if (zone->type == dns_zone_redirect)
13348 break;
13349 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
13350 !isc_time_isepoch(&zone->refreshkeytime)) {
13351 if (isc_time_isepoch(&next) ||
13352 isc_time_compare(&zone->refreshkeytime, &next) < 0)
13353 next = zone->refreshkeytime;
13354 }
13355 if (!isc_time_isepoch(&zone->resigntime)) {
13356 if (isc_time_isepoch(&next) ||
13357 isc_time_compare(&zone->resigntime, &next) < 0)
13358 next = zone->resigntime;
13359 }
13360 if (!isc_time_isepoch(&zone->keywarntime)) {
13361 if (isc_time_isepoch(&next) ||
13362 isc_time_compare(&zone->keywarntime, &next) < 0)
13363 next = zone->keywarntime;
13364 }
13365 if (!isc_time_isepoch(&zone->signingtime)) {
13366 if (isc_time_isepoch(&next) ||
13367 isc_time_compare(&zone->signingtime, &next) < 0)
13368 next = zone->signingtime;
13369 }
13370 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
13371 if (isc_time_isepoch(&next) ||
13372 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
13373 next = zone->nsec3chaintime;
13374 }
13375 break;
13376
13377 case dns_zone_slave:
13378 case dns_zone_mirror:
13379 treat_as_slave:
13380 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
13381 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
13382 next = zone->notifytime;
13383 /* FALLTHROUGH */
13384
13385 case dns_zone_stub:
13386 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
13387 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
13388 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
13389 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
13390 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
13391 !isc_time_isepoch(&zone->refreshtime) &&
13392 (isc_time_isepoch(&next) ||
13393 isc_time_compare(&zone->refreshtime, &next) < 0))
13394 next = zone->refreshtime;
13395 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
13396 !isc_time_isepoch(&zone->expiretime)) {
13397 if (isc_time_isepoch(&next) ||
13398 isc_time_compare(&zone->expiretime, &next) < 0)
13399 next = zone->expiretime;
13400 }
13401 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13402 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13403 INSIST(!isc_time_isepoch(&zone->dumptime));
13404 if (isc_time_isepoch(&next) ||
13405 isc_time_compare(&zone->dumptime, &next) < 0)
13406 next = zone->dumptime;
13407 }
13408 break;
13409
13410 case dns_zone_key:
13411 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13412 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13413 INSIST(!isc_time_isepoch(&zone->dumptime));
13414 if (isc_time_isepoch(&next) ||
13415 isc_time_compare(&zone->dumptime, &next) < 0)
13416 next = zone->dumptime;
13417 }
13418 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
13419 if (isc_time_isepoch(&next) ||
13420 (!isc_time_isepoch(&zone->refreshkeytime) &&
13421 isc_time_compare(&zone->refreshkeytime, &next) < 0))
13422 next = zone->refreshkeytime;
13423 }
13424 break;
13425
13426 default:
13427 break;
13428 }
13429
13430 if (isc_time_isepoch(&next)) {
13431 zone_debuglog(zone, me, 10, "settimer inactive");
13432 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
13433 NULL, NULL, true);
13434 if (result != ISC_R_SUCCESS)
13435 dns_zone_log(zone, ISC_LOG_ERROR,
13436 "could not deactivate zone timer: %s",
13437 isc_result_totext(result));
13438 } else {
13439 if (isc_time_compare(&next, now) <= 0)
13440 next = *now;
13441 result = isc_timer_reset(zone->timer, isc_timertype_once,
13442 &next, NULL, true);
13443 if (result != ISC_R_SUCCESS)
13444 dns_zone_log(zone, ISC_LOG_ERROR,
13445 "could not reset zone timer: %s",
13446 isc_result_totext(result));
13447 }
13448}
13449
13450static void
13451cancel_refresh(dns_zone_t *zone) {
13452 const char me[] = "cancel_refresh";
13453 isc_time_t now;
13454
13455 /*
13456 * 'zone' locked by caller.
13457 */
13458
13459 REQUIRE(DNS_ZONE_VALID(zone));
13460 REQUIRE(LOCKED_ZONE(zone));
13461
13462 ENTER;
13463
13464 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13465 TIME_NOW(&now);
13466 zone_settimer(zone, &now);
13467}
13468
13469static isc_result_t
13470notify_createmessage(dns_zone_t *zone, unsigned int flags,
13471 dns_message_t **messagep)
13472{
13473 dns_db_t *zonedb = NULL;
13474 dns_dbnode_t *node = NULL;
13475 dns_dbversion_t *version = NULL;
13476 dns_message_t *message = NULL;
13477 dns_rdataset_t rdataset;
13478 dns_rdata_t rdata = DNS_RDATA_INIT;
13479
13480 dns_name_t *tempname = NULL;
13481 dns_rdata_t *temprdata = NULL;
13482 dns_rdatalist_t *temprdatalist = NULL;
13483 dns_rdataset_t *temprdataset = NULL;
13484
13485 isc_result_t result;
13486 isc_region_t r;
13487 isc_buffer_t *b = NULL;
13488
13489 REQUIRE(DNS_ZONE_VALID(zone));
13490 REQUIRE(messagep != NULL && *messagep == NULL);
13491
13492 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
13493 &message);
13494 if (result != ISC_R_SUCCESS)
13495 return (result);
13496
13497 message->opcode = dns_opcode_notify;
13498 message->flags |= DNS_MESSAGEFLAG_AA;
13499 message->rdclass = zone->rdclass;
13500
13501 result = dns_message_gettempname(message, &tempname);
13502 if (result != ISC_R_SUCCESS)
13503 goto cleanup;
13504
13505 result = dns_message_gettemprdataset(message, &temprdataset);
13506 if (result != ISC_R_SUCCESS)
13507 goto cleanup;
13508
13509 /*
13510 * Make question.
13511 */
13512 dns_name_init(tempname, NULL);
13513 dns_name_clone(&zone->origin, tempname);
13514 dns_rdataset_makequestion(temprdataset, zone->rdclass,
13515 dns_rdatatype_soa);
13516 ISC_LIST_APPEND(tempname->list, temprdataset, link);
13517 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
13518 tempname = NULL;
13519 temprdataset = NULL;
13520
13521 if ((flags & DNS_NOTIFY_NOSOA) != 0)
13522 goto done;
13523
13524 result = dns_message_gettempname(message, &tempname);
13525 if (result != ISC_R_SUCCESS)
13526 goto soa_cleanup;
13527 result = dns_message_gettemprdata(message, &temprdata);
13528 if (result != ISC_R_SUCCESS)
13529 goto soa_cleanup;
13530 result = dns_message_gettemprdataset(message, &temprdataset);
13531 if (result != ISC_R_SUCCESS)
13532 goto soa_cleanup;
13533 result = dns_message_gettemprdatalist(message, &temprdatalist);
13534 if (result != ISC_R_SUCCESS)
13535 goto soa_cleanup;
13536
13537 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13538 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
13539 dns_db_attach(zone->db, &zonedb);
13540 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13541
13542 dns_name_init(tempname, NULL);
13543 dns_name_clone(&zone->origin, tempname);
13544 dns_db_currentversion(zonedb, &version);
13545 result = dns_db_findnode(zonedb, tempname, false, &node);
13546 if (result != ISC_R_SUCCESS)
13547 goto soa_cleanup;
13548
13549 dns_rdataset_init(&rdataset);
13550 result = dns_db_findrdataset(zonedb, node, version,
13551 dns_rdatatype_soa,
13552 dns_rdatatype_none, 0, &rdataset,
13553 NULL);
13554 if (result != ISC_R_SUCCESS)
13555 goto soa_cleanup;
13556 result = dns_rdataset_first(&rdataset);
13557 if (result != ISC_R_SUCCESS)
13558 goto soa_cleanup;
13559 dns_rdataset_current(&rdataset, &rdata);
13560 dns_rdata_toregion(&rdata, &r);
13561 result = isc_buffer_allocate(zone->mctx, &b, r.length);
13562 if (result != ISC_R_SUCCESS)
13563 goto soa_cleanup;
13564 isc_buffer_putmem(b, r.base, r.length);
13565 isc_buffer_usedregion(b, &r);
13566 dns_rdata_init(temprdata);
13567 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
13568 dns_message_takebuffer(message, &b);
13569 result = dns_rdataset_next(&rdataset);
13570 dns_rdataset_disassociate(&rdataset);
13571 if (result != ISC_R_NOMORE)
13572 goto soa_cleanup;
13573 temprdatalist->rdclass = rdata.rdclass;
13574 temprdatalist->type = rdata.type;
13575 temprdatalist->ttl = rdataset.ttl;
13576 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
13577
13578 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
13579 if (result != ISC_R_SUCCESS)
13580 goto soa_cleanup;
13581
13582 ISC_LIST_APPEND(tempname->list, temprdataset, link);
13583 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
13584 temprdatalist = NULL;
13585 temprdataset = NULL;
13586 temprdata = NULL;
13587 tempname = NULL;
13588
13589 soa_cleanup:
13590 if (node != NULL)
13591 dns_db_detachnode(zonedb, &node);
13592 if (version != NULL)
13593 dns_db_closeversion(zonedb, &version, false);
13594 if (zonedb != NULL)
13595 dns_db_detach(&zonedb);
13596 if (tempname != NULL)
13597 dns_message_puttempname(message, &tempname);
13598 if (temprdata != NULL)
13599 dns_message_puttemprdata(message, &temprdata);
13600 if (temprdataset != NULL)
13601 dns_message_puttemprdataset(message, &temprdataset);
13602 if (temprdatalist != NULL)
13603 dns_message_puttemprdatalist(message, &temprdatalist);
13604
13605 done:
13606 *messagep = message;
13607 return (ISC_R_SUCCESS);
13608
13609 cleanup:
13610 if (tempname != NULL)
13611 dns_message_puttempname(message, &tempname);
13612 if (temprdataset != NULL)
13613 dns_message_puttemprdataset(message, &temprdataset);
13614 dns_message_destroy(&message);
13615 return (result);
13616}
13617
13618isc_result_t
13619dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
13620 isc_sockaddr_t *to, dns_message_t *msg)
13621{
13622 unsigned int i;
13623 dns_rdata_soa_t soa;
13624 dns_rdataset_t *rdataset = NULL;
13625 dns_rdata_t rdata = DNS_RDATA_INIT;
13626 isc_result_t result;
13627 char fromtext[ISC_SOCKADDR_FORMATSIZE];
13628 int match = 0;
13629 isc_netaddr_t netaddr;
13630 uint32_t serial = 0;
13631 bool have_serial = false;
13632 dns_tsigkey_t *tsigkey;
13633 dns_name_t *tsig;
13634
13635 REQUIRE(DNS_ZONE_VALID(zone));
13636
13637 /*
13638 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
13639 * ROLLOVER.
13640 *
13641 * SOA: RFC1996
13642 * Check that 'from' is a valid notify source, (zone->masters).
13643 * Return DNS_R_REFUSED if not.
13644 *
13645 * If the notify message contains a serial number check it
13646 * against the zones serial and return if <= current serial
13647 *
13648 * If a refresh check is progress, if so just record the
13649 * fact we received a NOTIFY and from where and return.
13650 * We will perform a new refresh check when the current one
13651 * completes. Return ISC_R_SUCCESS.
13652 *
13653 * Otherwise initiate a refresh check using 'from' as the
13654 * first address to check. Return ISC_R_SUCCESS.
13655 */
13656
13657 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
13658
13659 /*
13660 * Notify messages are processed by the raw zone.
13661 */
13662 LOCK_ZONE(zone);
13663 INSIST(zone != zone->raw);
13664 if (inline_secure(zone)) {
13665 result = dns_zone_notifyreceive(zone->raw, from, to, msg);
13666 UNLOCK_ZONE(zone);
13667 return (result);
13668 }
13669 /*
13670 * We only handle NOTIFY (SOA) at the present.
13671 */
13672 if (isc_sockaddr_pf(from) == PF_INET)
13673 inc_stats(zone, dns_zonestatscounter_notifyinv4);
13674 else
13675 inc_stats(zone, dns_zonestatscounter_notifyinv6);
13676 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
13677 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
13678 dns_rdatatype_soa, dns_rdatatype_none,
13679 NULL, NULL) != ISC_R_SUCCESS) {
13680 UNLOCK_ZONE(zone);
13681 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
13682 dns_zone_log(zone, ISC_LOG_NOTICE,
13683 "NOTIFY with no "
13684 "question section from: %s", fromtext);
13685 return (DNS_R_FORMERR);
13686 }
13687 dns_zone_log(zone, ISC_LOG_NOTICE,
13688 "NOTIFY zone does not match");
13689 return (DNS_R_NOTIMP);
13690 }
13691
13692 /*
13693 * If we are a master zone just succeed.
13694 */
13695 if (zone->type == dns_zone_master) {
13696 UNLOCK_ZONE(zone);
13697 return (ISC_R_SUCCESS);
13698 }
13699
13700 isc_netaddr_fromsockaddr(&netaddr, from);
13701 for (i = 0; i < zone->masterscnt; i++) {
13702 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
13703 break;
13704 if (zone->view->aclenv.match_mapped &&
13705 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
13706 isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
13707 isc_netaddr_t na1, na2;
13708 isc_netaddr_fromv4mapped(&na1, &netaddr);
13709 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
13710 if (isc_netaddr_equal(&na1, &na2))
13711 break;
13712 }
13713 }
13714
13715 /*
13716 * Accept notify requests from non masters if they are on
13717 * 'zone->notify_acl'.
13718 */
13719 tsigkey = dns_message_gettsigkey(msg);
13720 tsig = dns_tsigkey_identity(tsigkey);
13721 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
13722 (dns_acl_match(&netaddr, tsig, zone->notify_acl,
13723 &zone->view->aclenv, &match,
13724 NULL) == ISC_R_SUCCESS) &&
13725 match > 0)
13726 {
13727 /* Accept notify. */
13728 } else if (i >= zone->masterscnt) {
13729 UNLOCK_ZONE(zone);
13730 dns_zone_log(zone, ISC_LOG_INFO,
13731 "refused notify from non-master: %s", fromtext);
13732 inc_stats(zone, dns_zonestatscounter_notifyrej);
13733 return (DNS_R_REFUSED);
13734 }
13735
13736 /*
13737 * If the zone is loaded and there are answers check the serial
13738 * to see if we need to do a refresh. Do not worry about this
13739 * check if we are a dialup zone as we use the notify request
13740 * to trigger a refresh check.
13741 */
13742 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
13743 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
13744 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
13745 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
13746 &zone->origin,
13747 dns_rdatatype_soa,
13748 dns_rdatatype_none, NULL,
13749 &rdataset);
13750 if (result == ISC_R_SUCCESS)
13751 result = dns_rdataset_first(rdataset);
13752 if (result == ISC_R_SUCCESS) {
13753 uint32_t oldserial;
13754 unsigned int soacount;
13755
13756 dns_rdataset_current(rdataset, &rdata);
13757 result = dns_rdata_tostruct(&rdata, &soa, NULL);
13758 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13759 serial = soa.serial;
13760 have_serial = true;
13761 /*
13762 * The following should safely be performed without DB
13763 * lock and succeed in this context.
13764 */
13765 result = zone_get_from_db(zone, zone->db, NULL,
13766 &soacount, &oldserial, NULL,
13767 NULL, NULL, NULL, NULL);
13768 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13769 RUNTIME_CHECK(soacount > 0U);
13770 if (isc_serial_le(serial, oldserial)) {
13771 dns_zone_log(zone,
13772 ISC_LOG_INFO,
13773 "notify from %s: "
13774 "zone is up to date",
13775 fromtext);
13776 UNLOCK_ZONE(zone);
13777 return (ISC_R_SUCCESS);
13778 }
13779 }
13780 }
13781
13782 /*
13783 * If we got this far and there was a refresh in progress just
13784 * let it complete. Record where we got the notify from so we
13785 * can perform a refresh check when the current one completes
13786 */
13787 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
13788 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13789 zone->notifyfrom = *from;
13790 UNLOCK_ZONE(zone);
13791 if (have_serial)
13792 dns_zone_log(zone, ISC_LOG_INFO,
13793 "notify from %s: serial %u: refresh in "
13794 "progress, refresh check queued",
13795 fromtext, serial);
13796 else
13797 dns_zone_log(zone, ISC_LOG_INFO,
13798 "notify from %s: refresh in progress, "
13799 "refresh check queued", fromtext);
13800 return (ISC_R_SUCCESS);
13801 }
13802 if (have_serial)
13803 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
13804 fromtext, serial);
13805 else
13806 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
13807 fromtext);
13808 zone->notifyfrom = *from;
13809 UNLOCK_ZONE(zone);
13810
13811 if (to != NULL) {
13812 dns_zonemgr_unreachabledel(zone->zmgr, from, to);
13813 }
13814 dns_zone_refresh(zone);
13815 return (ISC_R_SUCCESS);
13816}
13817
13818void
13819dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
13820
13821 REQUIRE(DNS_ZONE_VALID(zone));
13822
13823 LOCK_ZONE(zone);
13824 if (zone->notify_acl != NULL)
13825 dns_acl_detach(&zone->notify_acl);
13826 dns_acl_attach(acl, &zone->notify_acl);
13827 UNLOCK_ZONE(zone);
13828}
13829
13830void
13831dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
13832
13833 REQUIRE(DNS_ZONE_VALID(zone));
13834
13835 LOCK_ZONE(zone);
13836 if (zone->query_acl != NULL)
13837 dns_acl_detach(&zone->query_acl);
13838 dns_acl_attach(acl, &zone->query_acl);
13839 UNLOCK_ZONE(zone);
13840}
13841
13842void
13843dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
13844
13845 REQUIRE(DNS_ZONE_VALID(zone));
13846
13847 LOCK_ZONE(zone);
13848 if (zone->queryon_acl != NULL)
13849 dns_acl_detach(&zone->queryon_acl);
13850 dns_acl_attach(acl, &zone->queryon_acl);
13851 UNLOCK_ZONE(zone);
13852}
13853
13854void
13855dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
13856
13857 REQUIRE(DNS_ZONE_VALID(zone));
13858
13859 LOCK_ZONE(zone);
13860 if (zone->update_acl != NULL)
13861 dns_acl_detach(&zone->update_acl);
13862 dns_acl_attach(acl, &zone->update_acl);
13863 UNLOCK_ZONE(zone);
13864}
13865
13866void
13867dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
13868
13869 REQUIRE(DNS_ZONE_VALID(zone));
13870
13871 LOCK_ZONE(zone);
13872 if (zone->forward_acl != NULL)
13873 dns_acl_detach(&zone->forward_acl);
13874 dns_acl_attach(acl, &zone->forward_acl);
13875 UNLOCK_ZONE(zone);
13876}
13877
13878void
13879dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
13880
13881 REQUIRE(DNS_ZONE_VALID(zone));
13882
13883 LOCK_ZONE(zone);
13884 if (zone->xfr_acl != NULL)
13885 dns_acl_detach(&zone->xfr_acl);
13886 dns_acl_attach(acl, &zone->xfr_acl);
13887 UNLOCK_ZONE(zone);
13888}
13889
13890dns_acl_t *
13891dns_zone_getnotifyacl(dns_zone_t *zone) {
13892
13893 REQUIRE(DNS_ZONE_VALID(zone));
13894
13895 return (zone->notify_acl);
13896}
13897
13898dns_acl_t *
13899dns_zone_getqueryacl(dns_zone_t *zone) {
13900
13901 REQUIRE(DNS_ZONE_VALID(zone));
13902
13903 return (zone->query_acl);
13904}
13905
13906dns_acl_t *
13907dns_zone_getqueryonacl(dns_zone_t *zone) {
13908
13909 REQUIRE(DNS_ZONE_VALID(zone));
13910
13911 return (zone->queryon_acl);
13912}
13913
13914dns_acl_t *
13915dns_zone_getupdateacl(dns_zone_t *zone) {
13916
13917 REQUIRE(DNS_ZONE_VALID(zone));
13918
13919 return (zone->update_acl);
13920}
13921
13922dns_acl_t *
13923dns_zone_getforwardacl(dns_zone_t *zone) {
13924
13925 REQUIRE(DNS_ZONE_VALID(zone));
13926
13927 return (zone->forward_acl);
13928}
13929
13930dns_acl_t *
13931dns_zone_getxfracl(dns_zone_t *zone) {
13932
13933 REQUIRE(DNS_ZONE_VALID(zone));
13934
13935 return (zone->xfr_acl);
13936}
13937
13938void
13939dns_zone_clearupdateacl(dns_zone_t *zone) {
13940
13941 REQUIRE(DNS_ZONE_VALID(zone));
13942
13943 LOCK_ZONE(zone);
13944 if (zone->update_acl != NULL)
13945 dns_acl_detach(&zone->update_acl);
13946 UNLOCK_ZONE(zone);
13947}
13948
13949void
13950dns_zone_clearforwardacl(dns_zone_t *zone) {
13951
13952 REQUIRE(DNS_ZONE_VALID(zone));
13953
13954 LOCK_ZONE(zone);
13955 if (zone->forward_acl != NULL)
13956 dns_acl_detach(&zone->forward_acl);
13957 UNLOCK_ZONE(zone);
13958}
13959
13960void
13961dns_zone_clearnotifyacl(dns_zone_t *zone) {
13962
13963 REQUIRE(DNS_ZONE_VALID(zone));
13964
13965 LOCK_ZONE(zone);
13966 if (zone->notify_acl != NULL)
13967 dns_acl_detach(&zone->notify_acl);
13968 UNLOCK_ZONE(zone);
13969}
13970
13971void
13972dns_zone_clearqueryacl(dns_zone_t *zone) {
13973
13974 REQUIRE(DNS_ZONE_VALID(zone));
13975
13976 LOCK_ZONE(zone);
13977 if (zone->query_acl != NULL)
13978 dns_acl_detach(&zone->query_acl);
13979 UNLOCK_ZONE(zone);
13980}
13981
13982void
13983dns_zone_clearqueryonacl(dns_zone_t *zone) {
13984
13985 REQUIRE(DNS_ZONE_VALID(zone));
13986
13987 LOCK_ZONE(zone);
13988 if (zone->queryon_acl != NULL)
13989 dns_acl_detach(&zone->queryon_acl);
13990 UNLOCK_ZONE(zone);
13991}
13992
13993void
13994dns_zone_clearxfracl(dns_zone_t *zone) {
13995
13996 REQUIRE(DNS_ZONE_VALID(zone));
13997
13998 LOCK_ZONE(zone);
13999 if (zone->xfr_acl != NULL)
14000 dns_acl_detach(&zone->xfr_acl);
14001 UNLOCK_ZONE(zone);
14002}
14003
14004bool
14005dns_zone_getupdatedisabled(dns_zone_t *zone) {
14006 REQUIRE(DNS_ZONE_VALID(zone));
14007 return (zone->update_disabled);
14008
14009}
14010
14011void
14012dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
14013 REQUIRE(DNS_ZONE_VALID(zone));
14014 zone->update_disabled = state;
14015}
14016
14017bool
14018dns_zone_getzeronosoattl(dns_zone_t *zone) {
14019 REQUIRE(DNS_ZONE_VALID(zone));
14020 return (zone->zero_no_soa_ttl);
14021
14022}
14023
14024void
14025dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
14026 REQUIRE(DNS_ZONE_VALID(zone));
14027 zone->zero_no_soa_ttl = state;
14028}
14029
14030void
14031dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
14032 REQUIRE(DNS_ZONE_VALID(zone));
14033
14034 zone->check_names = severity;
14035}
14036
14037dns_severity_t
14038dns_zone_getchecknames(dns_zone_t *zone) {
14039 REQUIRE(DNS_ZONE_VALID(zone));
14040
14041 return (zone->check_names);
14042}
14043
14044void
14045dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
14046 REQUIRE(DNS_ZONE_VALID(zone));
14047
14048 zone->journalsize = size;
14049}
14050
14051int32_t
14052dns_zone_getjournalsize(dns_zone_t *zone) {
14053 REQUIRE(DNS_ZONE_VALID(zone));
14054
14055 return (zone->journalsize);
14056}
14057
14058static void
14059zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
14060 isc_result_t result = ISC_R_FAILURE;
14061 isc_buffer_t buffer;
14062
14063 REQUIRE(buf != NULL);
14064 REQUIRE(length > 1U);
14065
14066 /*
14067 * Leave space for terminating '\0'.
14068 */
14069 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14070 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
14071 if (dns_name_dynamic(&zone->origin))
14072 result = dns_name_totext(&zone->origin, true, &buffer);
14073 if (result != ISC_R_SUCCESS &&
14074 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
14075 isc_buffer_putstr(&buffer, "<UNKNOWN>");
14076
14077 if (isc_buffer_availablelength(&buffer) > 0)
14078 isc_buffer_putstr(&buffer, "/");
14079 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
14080 }
14081
14082 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
14083 strcmp(zone->view->name, "_default") != 0 &&
14084 strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
14085 isc_buffer_putstr(&buffer, "/");
14086 isc_buffer_putstr(&buffer, zone->view->name);
14087 }
14088 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
14089 isc_buffer_putstr(&buffer, " (signed)");
14090 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
14091 isc_buffer_putstr(&buffer, " (unsigned)");
14092
14093 buf[isc_buffer_usedlength(&buffer)] = '\0';
14094}
14095
14096static void
14097zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
14098 isc_result_t result = ISC_R_FAILURE;
14099 isc_buffer_t buffer;
14100
14101 REQUIRE(buf != NULL);
14102 REQUIRE(length > 1U);
14103
14104 /*
14105 * Leave space for terminating '\0'.
14106 */
14107 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14108 if (dns_name_dynamic(&zone->origin))
14109 result = dns_name_totext(&zone->origin, true, &buffer);
14110 if (result != ISC_R_SUCCESS &&
14111 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
14112 isc_buffer_putstr(&buffer, "<UNKNOWN>");
14113
14114 buf[isc_buffer_usedlength(&buffer)] = '\0';
14115}
14116
14117static void
14118zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
14119 isc_buffer_t buffer;
14120
14121 REQUIRE(buf != NULL);
14122 REQUIRE(length > 1U);
14123
14124 /*
14125 * Leave space for terminating '\0'.
14126 */
14127 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14128 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
14129
14130 buf[isc_buffer_usedlength(&buffer)] = '\0';
14131}
14132
14133static void
14134zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
14135 isc_buffer_t buffer;
14136
14137 REQUIRE(buf != NULL);
14138 REQUIRE(length > 1U);
14139
14140
14141 /*
14142 * Leave space for terminating '\0'.
14143 */
14144 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14145
14146 if (zone->view == NULL) {
14147 isc_buffer_putstr(&buffer, "_none");
14148 } else if (strlen(zone->view->name)
14149 < isc_buffer_availablelength(&buffer)) {
14150 isc_buffer_putstr(&buffer, zone->view->name);
14151 } else {
14152 isc_buffer_putstr(&buffer, "_toolong");
14153 }
14154
14155 buf[isc_buffer_usedlength(&buffer)] = '\0';
14156}
14157
14158void
14159dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
14160 REQUIRE(DNS_ZONE_VALID(zone));
14161 REQUIRE(buf != NULL);
14162 zone_namerd_tostr(zone, buf, length);
14163}
14164
14165void
14166dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
14167 REQUIRE(DNS_ZONE_VALID(zone));
14168 REQUIRE(buf != NULL);
14169 zone_name_tostr(zone, buf, length);
14170}
14171
14172void
14173dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
14174 const char *prefix, const char *fmt, va_list ap)
14175{
14176 char message[4096];
14177 const char *zstr;
14178
14179 if (!isc_log_wouldlog(dns_lctx, level)) {
14180 return;
14181 }
14182
14183 vsnprintf(message, sizeof(message), fmt, ap);
14184
14185 switch (zone->type) {
14186 case dns_zone_key:
14187 zstr = "managed-keys-zone";
14188 break;
14189 case dns_zone_redirect:
14190 zstr = "redirect-zone";
14191 break;
14192 default:
14193 zstr = "zone ";
14194 }
14195
14196 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
14197 "%s%s%s%s: %s",
14198 (prefix != NULL ? prefix : ""),
14199 (prefix != NULL ? ": " : ""),
14200 zstr, zone->strnamerd, message);
14201}
14202
14203static void
14204notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
14205 va_list ap;
14206
14207 va_start(ap, fmt);
14208 dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
14209 va_end(ap);
14210}
14211
14212void
14213dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
14214 int level, const char *fmt, ...)
14215{
14216 va_list ap;
14217
14218 va_start(ap, fmt);
14219 dns_zone_logv(zone, category, level, NULL, fmt, ap);
14220 va_end(ap);
14221}
14222
14223void
14224dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
14225 va_list ap;
14226
14227 va_start(ap, fmt);
14228 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
14229 va_end(ap);
14230}
14231
14232static void
14233zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
14234 const char *fmt, ...)
14235{
14236 int level = ISC_LOG_DEBUG(debuglevel);
14237 va_list ap;
14238
14239 va_start(ap, fmt);
14240 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
14241 va_end(ap);
14242}
14243
14244static void
14245dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
14246 va_list ap;
14247
14248 va_start(ap, fmt);
14249 dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
14250 va_end(ap);
14251}
14252
14253static int
14254message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
14255{
14256 isc_result_t result;
14257 dns_name_t *name;
14258 dns_rdataset_t *curr;
14259 int count = 0;
14260
14261 result = dns_message_firstname(msg, section);
14262 while (result == ISC_R_SUCCESS) {
14263 name = NULL;
14264 dns_message_currentname(msg, section, &name);
14265
14266 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
14267 curr = ISC_LIST_PREV(curr, link)) {
14268 if (curr->type == type)
14269 count++;
14270 }
14271 result = dns_message_nextname(msg, section);
14272 }
14273
14274 return (count);
14275}
14276
14277void
14278dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
14279 REQUIRE(DNS_ZONE_VALID(zone));
14280
14281 zone->maxxfrin = maxxfrin;
14282}
14283
14284uint32_t
14285dns_zone_getmaxxfrin(dns_zone_t *zone) {
14286 REQUIRE(DNS_ZONE_VALID(zone));
14287
14288 return (zone->maxxfrin);
14289}
14290
14291void
14292dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
14293 REQUIRE(DNS_ZONE_VALID(zone));
14294 zone->maxxfrout = maxxfrout;
14295}
14296
14297uint32_t
14298dns_zone_getmaxxfrout(dns_zone_t *zone) {
14299 REQUIRE(DNS_ZONE_VALID(zone));
14300
14301 return (zone->maxxfrout);
14302}
14303
14304dns_zonetype_t
14305dns_zone_gettype(dns_zone_t *zone) {
14306 REQUIRE(DNS_ZONE_VALID(zone));
14307
14308 return (zone->type);
14309}
14310
14311dns_zonetype_t
14312dns_zone_getredirecttype(dns_zone_t *zone) {
14313 REQUIRE(DNS_ZONE_VALID(zone));
14314 REQUIRE(zone->type == dns_zone_redirect);
14315
14316 return (zone->masters == NULL ? dns_zone_master : dns_zone_slave);
14317}
14318
14319dns_name_t *
14320dns_zone_getorigin(dns_zone_t *zone) {
14321 REQUIRE(DNS_ZONE_VALID(zone));
14322
14323 return (&zone->origin);
14324}
14325
14326void
14327dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
14328 REQUIRE(DNS_ZONE_VALID(zone));
14329
14330 LOCK_ZONE(zone);
14331 if (zone->task != NULL)
14332 isc_task_detach(&zone->task);
14333 isc_task_attach(task, &zone->task);
14334 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14335 if (zone->db != NULL)
14336 dns_db_settask(zone->db, zone->task);
14337 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14338 UNLOCK_ZONE(zone);
14339}
14340
14341void
14342dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
14343 REQUIRE(DNS_ZONE_VALID(zone));
14344 isc_task_attach(zone->task, target);
14345}
14346
14347void
14348dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
14349 REQUIRE(DNS_ZONE_VALID(zone));
14350
14351 if (idlein == 0)
14352 idlein = DNS_DEFAULT_IDLEIN;
14353 zone->idlein = idlein;
14354}
14355
14356uint32_t
14357dns_zone_getidlein(dns_zone_t *zone) {
14358 REQUIRE(DNS_ZONE_VALID(zone));
14359
14360 return (zone->idlein);
14361}
14362
14363void
14364dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
14365 REQUIRE(DNS_ZONE_VALID(zone));
14366
14367 zone->idleout = idleout;
14368}
14369
14370uint32_t
14371dns_zone_getidleout(dns_zone_t *zone) {
14372 REQUIRE(DNS_ZONE_VALID(zone));
14373
14374 return (zone->idleout);
14375}
14376
14377static void
14378notify_done(isc_task_t *task, isc_event_t *event) {
14379 dns_requestevent_t *revent = (dns_requestevent_t *)event;
14380 dns_notify_t *notify;
14381 isc_result_t result;
14382 dns_message_t *message = NULL;
14383 isc_buffer_t buf;
14384 char rcode[128];
14385 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
14386
14387 UNUSED(task);
14388
14389 notify = event->ev_arg;
14390 REQUIRE(DNS_NOTIFY_VALID(notify));
14391 INSIST(task == notify->zone->task);
14392
14393 isc_buffer_init(&buf, rcode, sizeof(rcode));
14394 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
14395
14396 result = revent->result;
14397 if (result == ISC_R_SUCCESS)
14398 result = dns_message_create(notify->zone->mctx,
14399 DNS_MESSAGE_INTENTPARSE, &message);
14400 if (result == ISC_R_SUCCESS)
14401 result = dns_request_getresponse(revent->request, message,
14402 DNS_MESSAGEPARSE_PRESERVEORDER);
14403 if (result == ISC_R_SUCCESS)
14404 result = dns_rcode_totext(message->rcode, &buf);
14405 if (result == ISC_R_SUCCESS)
14406 notify_log(notify->zone, ISC_LOG_DEBUG(3),
14407 "notify response from %s: %.*s",
14408 addrbuf, (int)buf.used, rcode);
14409 else
14410 notify_log(notify->zone, ISC_LOG_DEBUG(2),
14411 "notify to %s failed: %s", addrbuf,
14412 dns_result_totext(result));
14413
14414 /*
14415 * Old bind's return formerr if they see a soa record. Retry w/o
14416 * the soa if we see a formerr and had sent a SOA.
14417 */
14418 isc_event_free(&event);
14419 if (message != NULL && message->rcode == dns_rcode_formerr &&
14420 (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
14421 bool startup;
14422
14423 notify->flags |= DNS_NOTIFY_NOSOA;
14424 dns_request_destroy(&notify->request);
14425 startup = (notify->flags & DNS_NOTIFY_STARTUP);
14426 result = notify_send_queue(notify, startup);
14427 if (result != ISC_R_SUCCESS)
14428 notify_destroy(notify, false);
14429 } else {
14430 if (result == ISC_R_TIMEDOUT)
14431 notify_log(notify->zone, ISC_LOG_DEBUG(1),
14432 "notify to %s: retries exceeded", addrbuf);
14433 notify_destroy(notify, false);
14434 }
14435 if (message != NULL)
14436 dns_message_destroy(&message);
14437}
14438
14439struct secure_event {
14440 isc_event_t e;
14441 dns_db_t *db;
14442 uint32_t serial;
14443};
14444
14445static void
14446update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
14447 UNUSED(arg);
14448 dns_zone_log(zone, level, "%s", message);
14449}
14450
14451static isc_result_t
14452sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
14453 uint32_t start, uint32_t end,
14454 dns_difftuple_t **soatuplep, dns_diff_t *diff)
14455{
14456 isc_result_t result;
14457 dns_difftuple_t *tuple = NULL;
14458 dns_diffop_t op = DNS_DIFFOP_ADD;
14459 int n_soa = 0;
14460
14461 REQUIRE(soatuplep != NULL);
14462
14463 if (start == end)
14464 return (DNS_R_UNCHANGED);
14465
14466 CHECK(dns_journal_iter_init(journal, start, end));
14467 for (result = dns_journal_first_rr(journal);
14468 result == ISC_R_SUCCESS;
14469 result = dns_journal_next_rr(journal))
14470 {
14471 dns_name_t *name = NULL;
14472 uint32_t ttl;
14473 dns_rdata_t *rdata = NULL;
14474 dns_journal_current_rr(journal, &name, &ttl, &rdata);
14475
14476 if (rdata->type == dns_rdatatype_soa) {
14477 n_soa++;
14478 if (n_soa == 2) {
14479 /*
14480 * Save the latest raw SOA record.
14481 */
14482 if (*soatuplep != NULL)
14483 dns_difftuple_free(soatuplep);
14484 CHECK(dns_difftuple_create(diff->mctx,
14485 DNS_DIFFOP_ADD,
14486 name, ttl, rdata,
14487 soatuplep));
14488 }
14489 if (n_soa == 3)
14490 n_soa = 1;
14491 continue;
14492 }
14493
14494 /* Sanity. */
14495 if (n_soa == 0) {
14496 dns_zone_log(raw, ISC_LOG_ERROR,
14497 "corrupt journal file: '%s'\n",
14498 raw->journal);
14499 return (ISC_R_FAILURE);
14500 }
14501
14502 if (zone->privatetype != 0 &&
14503 rdata->type == zone->privatetype)
14504 continue;
14505
14506 if (rdata->type == dns_rdatatype_nsec ||
14507 rdata->type == dns_rdatatype_rrsig ||
14508 rdata->type == dns_rdatatype_nsec3 ||
14509 rdata->type == dns_rdatatype_dnskey ||
14510 rdata->type == dns_rdatatype_nsec3param)
14511 continue;
14512
14513 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
14514
14515 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
14516 &tuple));
14517 dns_diff_appendminimal(diff, &tuple);
14518 }
14519 if (result == ISC_R_NOMORE)
14520 result = ISC_R_SUCCESS;
14521
14522 failure:
14523 return(result);
14524}
14525
14526static isc_result_t
14527sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
14528 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
14529 dns_diff_t *diff)
14530{
14531 isc_result_t result;
14532 dns_db_t *rawdb = NULL;
14533 dns_dbversion_t *rawver = NULL;
14534 dns_difftuple_t *tuple = NULL, *next;
14535 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
14536 dns_rdata_soa_t oldsoa, newsoa;
14537
14538 REQUIRE(DNS_ZONE_VALID(seczone));
14539 REQUIRE(soatuple != NULL && *soatuple == NULL);
14540
14541 if (!seczone->sourceserialset)
14542 return (DNS_R_UNCHANGED);
14543
14544 dns_db_attach(raw->db, &rawdb);
14545 dns_db_currentversion(rawdb, &rawver);
14546 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
14547 dns_db_closeversion(rawdb, &rawver, false);
14548 dns_db_detach(&rawdb);
14549
14550 if (result != ISC_R_SUCCESS)
14551 return (result);
14552
14553 for (tuple = ISC_LIST_HEAD(diff->tuples);
14554 tuple != NULL;
14555 tuple = next)
14556 {
14557 next = ISC_LIST_NEXT(tuple, link);
14558 if (tuple->rdata.type == dns_rdatatype_nsec ||
14559 tuple->rdata.type == dns_rdatatype_rrsig ||
14560 tuple->rdata.type == dns_rdatatype_dnskey ||
14561 tuple->rdata.type == dns_rdatatype_nsec3 ||
14562 tuple->rdata.type == dns_rdatatype_nsec3param)
14563 {
14564 ISC_LIST_UNLINK(diff->tuples, tuple, link);
14565 dns_difftuple_free(&tuple);
14566 continue;
14567 }
14568 if (tuple->rdata.type == dns_rdatatype_soa) {
14569 if (tuple->op == DNS_DIFFOP_DEL) {
14570 INSIST(oldtuple == NULL);
14571 oldtuple = tuple;
14572 }
14573 if (tuple->op == DNS_DIFFOP_ADD) {
14574 INSIST(newtuple == NULL);
14575 newtuple = tuple;
14576 }
14577 }
14578 }
14579
14580 if (oldtuple != NULL && newtuple != NULL) {
14581
14582 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
14583 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14584
14585 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
14586 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14587
14588 /*
14589 * If the SOA records are the same except for the serial
14590 * remove them from the diff.
14591 */
14592 if (oldsoa.refresh == newsoa.refresh &&
14593 oldsoa.retry == newsoa.retry &&
14594 oldsoa.minimum == newsoa.minimum &&
14595 oldsoa.expire == newsoa.expire &&
14596 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
14597 dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
14598 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
14599 dns_difftuple_free(&oldtuple);
14600 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
14601 dns_difftuple_free(&newtuple);
14602 }
14603 }
14604
14605 if (ISC_LIST_EMPTY(diff->tuples))
14606 return (DNS_R_UNCHANGED);
14607
14608 /*
14609 * If there are still SOA records in the diff they can now be removed
14610 * saving the new SOA record.
14611 */
14612 if (oldtuple != NULL) {
14613 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
14614 dns_difftuple_free(&oldtuple);
14615 }
14616
14617 if (newtuple != NULL) {
14618 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
14619 *soatuple = newtuple;
14620 }
14621
14622 return (ISC_R_SUCCESS);
14623}
14624
14625static void
14626receive_secure_serial(isc_task_t *task, isc_event_t *event) {
14627 static char me[] = "receive_secure_serial";
14628 isc_result_t result = ISC_R_SUCCESS;
14629 dns_journal_t *rjournal = NULL;
14630 dns_journal_t *sjournal = NULL;
14631 uint32_t start, end;
14632 dns_zone_t *zone;
14633 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
14634 dns_update_log_t log = { update_log_cb, NULL };
14635 uint32_t newserial = 0, desired = 0;
14636 isc_time_t timenow;
14637
14638 UNUSED(task);
14639
14640 zone = event->ev_arg;
14641 end = ((struct secure_event *)event)->serial;
14642
14643 ENTER;
14644
14645 LOCK_ZONE(zone);
14646
14647 /*
14648 * If we are already processing a receive secure serial event
14649 * for the zone, just queue the new one and exit.
14650 */
14651 if (zone->rss_event != NULL && zone->rss_event != event) {
14652 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
14653 UNLOCK_ZONE(zone);
14654 return;
14655 }
14656
14657 nextevent:
14658 if (zone->rss_event != NULL) {
14659 INSIST(zone->rss_event == event);
14660 UNLOCK_ZONE(zone);
14661 } else {
14662 zone->rss_event = event;
14663 dns_diff_init(zone->mctx, &zone->rss_diff);
14664
14665 /*
14666 * zone->db may be NULL, if the load from disk failed.
14667 */
14668 result = ISC_R_SUCCESS;
14669 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14670 if (zone->db != NULL)
14671 dns_db_attach(zone->db, &zone->rss_db);
14672 else
14673 result = ISC_R_FAILURE;
14674 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14675
14676 if (result == ISC_R_SUCCESS && zone->raw != NULL)
14677 dns_zone_attach(zone->raw, &zone->rss_raw);
14678 else
14679 result = ISC_R_FAILURE;
14680
14681 UNLOCK_ZONE(zone);
14682
14683 CHECK(result);
14684
14685 /*
14686 * We first attempt to sync the raw zone to the secure zone
14687 * by using the raw zone's journal, applying all the deltas
14688 * from the latest source-serial of the secure zone up to
14689 * the current serial number of the raw zone.
14690 *
14691 * If that fails, then we'll fall back to a direct comparison
14692 * between raw and secure zones.
14693 */
14694 CHECK(dns_journal_open(zone->rss_raw->mctx,
14695 zone->rss_raw->journal,
14696 DNS_JOURNAL_WRITE, &rjournal));
14697
14698 result = dns_journal_open(zone->mctx, zone->journal,
14699 DNS_JOURNAL_READ, &sjournal);
14700 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
14701 goto failure;
14702
14703 if (!dns_journal_get_sourceserial(rjournal, &start)) {
14704 start = dns_journal_first_serial(rjournal);
14705 dns_journal_set_sourceserial(rjournal, start);
14706 }
14707 if (sjournal != NULL) {
14708 uint32_t serial;
14709 /*
14710 * We read the secure journal first, if that
14711 * exists use its value provided it is greater
14712 * that from the raw journal.
14713 */
14714 if (dns_journal_get_sourceserial(sjournal, &serial)) {
14715 if (isc_serial_gt(serial, start))
14716 start = serial;
14717 }
14718 dns_journal_destroy(&sjournal);
14719 }
14720
14721 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
14722 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
14723
14724 /*
14725 * Try to apply diffs from the raw zone's journal to the secure
14726 * zone. If that fails, we recover by syncing up the databases
14727 * directly.
14728 */
14729 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
14730 start, end, &soatuple,
14731 &zone->rss_diff);
14732 if (result == DNS_R_UNCHANGED)
14733 goto failure;
14734 else if (result != ISC_R_SUCCESS)
14735 CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
14736 zone->rss_oldver, &soatuple,
14737 &zone->rss_diff));
14738
14739 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
14740 zone->rss_newver));
14741
14742 if (soatuple != NULL) {
14743 uint32_t oldserial;
14744
14745 CHECK(dns_db_createsoatuple(zone->rss_db,
14746 zone->rss_oldver,
14747 zone->rss_diff.mctx,
14748 DNS_DIFFOP_DEL, &tuple));
14749 oldserial = dns_soa_getserial(&tuple->rdata);
14750 newserial = desired =
14751 dns_soa_getserial(&soatuple->rdata);
14752 if (!isc_serial_gt(newserial, oldserial)) {
14753 newserial = oldserial + 1;
14754 if (newserial == 0)
14755 newserial++;
14756 dns_soa_setserial(newserial, &soatuple->rdata);
14757 }
14758 CHECK(do_one_tuple(&tuple, zone->rss_db,
14759 zone->rss_newver, &zone->rss_diff));
14760 CHECK(do_one_tuple(&soatuple, zone->rss_db,
14761 zone->rss_newver, &zone->rss_diff));
14762 } else
14763 CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
14764 &zone->rss_diff, zone->mctx,
14765 zone->updatemethod));
14766
14767 }
14768 result = dns_update_signaturesinc(&log, zone, zone->rss_db,
14769 zone->rss_oldver, zone->rss_newver,
14770 &zone->rss_diff,
14771 zone->sigvalidityinterval,
14772 &zone->rss_state);
14773 if (result == DNS_R_CONTINUE) {
14774 if (rjournal != NULL)
14775 dns_journal_destroy(&rjournal);
14776 isc_task_send(task, &event);
14777 return;
14778 }
14779 /*
14780 * If something went wrong while trying to update the secure zone and
14781 * the latter was already signed before, do not apply raw zone deltas
14782 * to it as that would break existing DNSSEC signatures. However, if
14783 * the secure zone was not yet signed (e.g. because no signing keys
14784 * were created for it), commence applying raw zone deltas to it so
14785 * that contents of the raw zone and the secure zone are kept in sync.
14786 */
14787 if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
14788 goto failure;
14789 }
14790
14791 if (rjournal == NULL)
14792 CHECK(dns_journal_open(zone->rss_raw->mctx,
14793 zone->rss_raw->journal,
14794 DNS_JOURNAL_WRITE, &rjournal));
14795 CHECK(zone_journal(zone, &zone->rss_diff, &end,
14796 "receive_secure_serial"));
14797
14798 dns_journal_set_sourceserial(rjournal, end);
14799 dns_journal_commit(rjournal);
14800
14801 LOCK_ZONE(zone);
14802 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14803
14804 zone->sourceserial = end;
14805 zone->sourceserialset = true;
14806 zone_needdump(zone, DNS_DUMP_DELAY);
14807
14808 TIME_NOW(&timenow);
14809 zone_settimer(zone, &timenow);
14810 UNLOCK_ZONE(zone);
14811
14812 dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
14813 dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
14814
14815 if (newserial != 0) {
14816 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
14817 newserial, desired);
14818 }
14819
14820 failure:
14821 isc_event_free(&zone->rss_event);
14822 event = ISC_LIST_HEAD(zone->rss_events);
14823
14824 if (zone->rss_raw != NULL)
14825 dns_zone_detach(&zone->rss_raw);
14826 if (result != ISC_R_SUCCESS)
14827 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
14828 dns_result_totext(result));
14829 if (tuple != NULL)
14830 dns_difftuple_free(&tuple);
14831 if (soatuple != NULL)
14832 dns_difftuple_free(&soatuple);
14833 if (zone->rss_db != NULL) {
14834 if (zone->rss_oldver != NULL)
14835 dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
14836 false);
14837 if (zone->rss_newver != NULL)
14838 dns_db_closeversion(zone->rss_db, &zone->rss_newver,
14839 false);
14840 dns_db_detach(&zone->rss_db);
14841 }
14842 INSIST(zone->rss_oldver == NULL);
14843 INSIST(zone->rss_newver == NULL);
14844 if (rjournal != NULL)
14845 dns_journal_destroy(&rjournal);
14846 dns_diff_clear(&zone->rss_diff);
14847
14848 if (event != NULL) {
14849 LOCK_ZONE(zone);
14850 INSIST(zone->irefs > 1);
14851 zone->irefs--;
14852 ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
14853 goto nextevent;
14854 }
14855 dns_zone_idetach(&zone);
14856}
14857
14858static isc_result_t
14859zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
14860 isc_event_t *e;
14861 dns_zone_t *dummy = NULL;
14862
14863 e = isc_event_allocate(zone->secure->mctx, zone,
14864 DNS_EVENT_ZONESECURESERIAL,
14865 receive_secure_serial, zone->secure,
14866 sizeof(struct secure_event));
14867 if (e == NULL)
14868 return (ISC_R_NOMEMORY);
14869 ((struct secure_event *)e)->serial = serial;
14870 INSIST(LOCKED_ZONE(zone->secure));
14871 zone_iattach(zone->secure, &dummy);
14872 isc_task_send(zone->secure->task, &e);
14873
14874 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
14875 return (ISC_R_SUCCESS);
14876}
14877
14878static isc_result_t
14879checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
14880 dns_rdataset_t *rdataset, uint32_t oldserial)
14881{
14882 dns_rdata_soa_t soa;
14883 dns_rdata_t rdata = DNS_RDATA_INIT;
14884 dns_rdatalist_t temprdatalist;
14885 dns_rdataset_t temprdataset;
14886 isc_buffer_t b;
14887 isc_result_t result;
14888 unsigned char buf[DNS_SOA_BUFFERSIZE];
14889 dns_fixedname_t fixed;
14890 dns_name_t *name;
14891
14892 result = dns_rdataset_first(rdataset);
14893 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14894 dns_rdataset_current(rdataset, &rdata);
14895 result = dns_rdata_tostruct(&rdata, &soa, NULL);
14896 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14897
14898 if (isc_serial_gt(soa.serial, oldserial))
14899 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
14900 NULL));
14901 /*
14902 * Always bump the serial.
14903 */
14904 oldserial++;
14905 if (oldserial == 0)
14906 oldserial++;
14907 soa.serial = oldserial;
14908
14909 /*
14910 * Construct a replacement rdataset.
14911 */
14912 dns_rdata_reset(&rdata);
14913 isc_buffer_init(&b, buf, sizeof(buf));
14914 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
14915 dns_rdatatype_soa, &soa, &b);
14916 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14917 dns_rdatalist_init(&temprdatalist);
14918 temprdatalist.rdclass = rdata.rdclass;
14919 temprdatalist.type = rdata.type;
14920 temprdatalist.ttl = rdataset->ttl;
14921 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
14922
14923 dns_rdataset_init(&temprdataset);
14924 result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
14925 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14926
14927 name = dns_fixedname_initname(&fixed);
14928 result = dns_db_nodefullname(db, node, name);
14929 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14930 dns_rdataset_getownercase(rdataset, name);
14931 dns_rdataset_setownercase(&temprdataset, name);
14932 return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
14933 0, NULL));
14934}
14935
14936/*
14937 * This function should populate an nsec3paramlist_t with the
14938 * nsecparam_t data from a zone.
14939 */
14940static isc_result_t
14941save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
14942 isc_result_t result;
14943 dns_dbnode_t *node = NULL;
14944 dns_rdataset_t rdataset, prdataset;
14945 dns_dbversion_t *version = NULL;
14946 nsec3param_t *nsec3param = NULL;
14947 nsec3param_t *nsec3p = NULL;
14948 nsec3param_t *next;
14949 dns_db_t *db = NULL;
14950 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
14951
14952 REQUIRE(DNS_ZONE_VALID(zone));
14953 REQUIRE(nsec3list != NULL);
14954 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
14955
14956 dns_rdataset_init(&rdataset);
14957 dns_rdataset_init(&prdataset);
14958
14959 dns_db_attach(zone->db, &db);
14960 CHECK(dns_db_getoriginnode(db, &node));
14961
14962 dns_db_currentversion(db, &version);
14963 result = dns_db_findrdataset(db, node, version,
14964 dns_rdatatype_nsec3param,
14965 dns_rdatatype_none, 0, &rdataset, NULL);
14966
14967 if (result != ISC_R_SUCCESS)
14968 goto getprivate;
14969
14970 /*
14971 * walk nsec3param rdataset making a list of parameters (note that
14972 * multiple simultaneous nsec3 chains are annoyingly legal -- this
14973 * is why we use an nsec3list, even tho we will usually only have
14974 * one)
14975 */
14976 for (result = dns_rdataset_first(&rdataset);
14977 result == ISC_R_SUCCESS;
14978 result = dns_rdataset_next(&rdataset))
14979 {
14980 dns_rdata_t rdata = DNS_RDATA_INIT;
14981 dns_rdata_t private = DNS_RDATA_INIT;
14982
14983 dns_rdataset_current(&rdataset, &rdata);
14984 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14985 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
14986 "looping through nsec3param data");
14987 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
14988 if (nsec3param == NULL)
14989 CHECK(ISC_R_NOMEMORY);
14990 ISC_LINK_INIT(nsec3param, link);
14991
14992 /*
14993 * now transfer the data from the rdata to
14994 * the nsec3param
14995 */
14996 dns_nsec3param_toprivate(&rdata, &private,
14997 zone->privatetype, nsec3param->data,
14998 sizeof(nsec3param->data));
14999 nsec3param->length = private.length;
15000 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
15001 }
15002
15003 getprivate:
15004 result = dns_db_findrdataset(db, node, version, zone->privatetype,
15005 dns_rdatatype_none, 0, &prdataset, NULL);
15006 if (result != ISC_R_SUCCESS)
15007 goto done;
15008
15009 /*
15010 * walk private type records, converting them to nsec3 parameters
15011 * using dns_nsec3param_fromprivate(), do the right thing based on
15012 * CREATE and REMOVE flags
15013 */
15014 for (result = dns_rdataset_first(&prdataset);
15015 result == ISC_R_SUCCESS;
15016 result = dns_rdataset_next(&prdataset))
15017 {
15018 dns_rdata_t rdata = DNS_RDATA_INIT;
15019 dns_rdata_t private = DNS_RDATA_INIT;
15020
15021 dns_rdataset_current(&prdataset, &private);
15022 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15023 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15024 "looping through nsec3param private data");
15025
15026 /*
15027 * Do we have a valid private record?
15028 */
15029 if (!dns_nsec3param_fromprivate(&private, &rdata,
15030 buf, sizeof(buf)))
15031 continue;
15032
15033 /*
15034 * Remove any NSEC3PARAM records scheduled to be removed.
15035 */
15036 if (NSEC3REMOVE(rdata.data[1])) {
15037 /*
15038 * Zero out the flags.
15039 */
15040 rdata.data[1] = 0;
15041
15042 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
15043 nsec3p != NULL;
15044 nsec3p = next)
15045 {
15046 next = ISC_LIST_NEXT(nsec3p, link);
15047
15048 if (nsec3p->length == rdata.length + 1 &&
15049 memcmp(rdata.data, nsec3p->data + 1,
15050 nsec3p->length - 1) == 0) {
15051 ISC_LIST_UNLINK(*nsec3list,
15052 nsec3p, link);
15053 isc_mem_put(zone->mctx, nsec3p,
15054 sizeof(nsec3param_t));
15055 }
15056 }
15057 continue;
15058 }
15059
15060 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
15061 if (nsec3param == NULL)
15062 CHECK(ISC_R_NOMEMORY);
15063 ISC_LINK_INIT(nsec3param, link);
15064
15065 /*
15066 * Copy the remaining private records so the nsec/nsec3
15067 * chain gets created.
15068 */
15069 INSIST(private.length <= sizeof(nsec3param->data));
15070 memmove(nsec3param->data, private.data, private.length);
15071 nsec3param->length = private.length;
15072 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
15073 }
15074
15075 done:
15076 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
15077 result = ISC_R_SUCCESS;
15078
15079 failure:
15080 if (node != NULL)
15081 dns_db_detachnode(db, &node);
15082 if (version != NULL)
15083 dns_db_closeversion(db, &version, false);
15084 if (db != NULL)
15085 dns_db_detach(&db);
15086 if (dns_rdataset_isassociated(&rdataset))
15087 dns_rdataset_disassociate(&rdataset);
15088 if (dns_rdataset_isassociated(&prdataset))
15089 dns_rdataset_disassociate(&prdataset);
15090 return (result);
15091}
15092
15093/*
15094 * Populate new zone db with private type records found by save_nsec3param().
15095 */
15096static isc_result_t
15097restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
15098 nsec3paramlist_t *nsec3list)
15099{
15100 isc_result_t result;
15101 dns_diff_t diff;
15102 dns_rdata_t rdata;
15103 nsec3param_t *nsec3p = NULL;
15104 nsec3param_t *next;
15105
15106 REQUIRE(DNS_ZONE_VALID(zone));
15107 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
15108
15109 dns_diff_init(zone->mctx, &diff);
15110
15111 /*
15112 * Loop through the list of private-type records, set the INITIAL
15113 * and CREATE flags, and the add the record to the apex of the tree
15114 * in db.
15115 */
15116 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
15117 nsec3p != NULL;
15118 nsec3p = next)
15119 {
15120 next = ISC_LIST_NEXT(nsec3p, link);
15121 dns_rdata_init(&rdata);
15122 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
15123 rdata.length = nsec3p->length;
15124 rdata.data = nsec3p->data;
15125 rdata.type = zone->privatetype;
15126 rdata.rdclass = zone->rdclass;
15127 result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
15128 &zone->origin, 0, &rdata);
15129 if (result != ISC_R_SUCCESS) {
15130 break;
15131 }
15132 }
15133
15134 dns_diff_clear(&diff);
15135 return (result);
15136}
15137
15138static void
15139receive_secure_db(isc_task_t *task, isc_event_t *event) {
15140 isc_result_t result;
15141 dns_zone_t *zone;
15142 dns_db_t *rawdb, *db = NULL;
15143 dns_dbnode_t *rawnode = NULL, *node = NULL;
15144 dns_fixedname_t fname;
15145 dns_name_t *name;
15146 dns_dbiterator_t *dbiterator = NULL;
15147 dns_rdatasetiter_t *rdsit = NULL;
15148 dns_rdataset_t rdataset;
15149 dns_dbversion_t *version = NULL;
15150 isc_time_t loadtime;
15151 unsigned int oldserial = 0;
15152 bool have_oldserial = false;
15153 nsec3paramlist_t nsec3list;
15154 isc_event_t *setnsec3param_event;
15155 dns_zone_t *dummy;
15156
15157 UNUSED(task);
15158
15159 ISC_LIST_INIT(nsec3list);
15160
15161 zone = event->ev_arg;
15162 rawdb = ((struct secure_event *)event)->db;
15163 isc_event_free(&event);
15164
15165 name = dns_fixedname_initname(&fname);
15166 dns_rdataset_init(&rdataset);
15167
15168 LOCK_ZONE(zone);
15169 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
15170 result = ISC_R_SHUTTINGDOWN;
15171 goto failure;
15172 }
15173
15174 TIME_NOW(&loadtime);
15175 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15176 if (zone->db != NULL) {
15177 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
15178 if (result == ISC_R_SUCCESS)
15179 have_oldserial = true;
15180
15181 /*
15182 * assemble nsec3parameters from the old zone, and set a flag
15183 * if any are found
15184 */
15185 result = save_nsec3param(zone, &nsec3list);
15186 if (result != ISC_R_SUCCESS) {
15187 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15188 goto failure;
15189 }
15190 }
15191 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15192
15193 result = dns_db_create(zone->mctx, zone->db_argv[0],
15194 &zone->origin, dns_dbtype_zone, zone->rdclass,
15195 zone->db_argc - 1, zone->db_argv + 1, &db);
15196 if (result != ISC_R_SUCCESS)
15197 goto failure;
15198
15199 result = dns_db_setgluecachestats(db, zone->gluecachestats);
15200 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
15201 goto failure;
15202 }
15203
15204 result = dns_db_newversion(db, &version);
15205 if (result != ISC_R_SUCCESS)
15206 goto failure;
15207
15208 result = dns_db_createiterator(rawdb, 0, &dbiterator);
15209 if (result != ISC_R_SUCCESS)
15210 goto failure;
15211
15212 for (result = dns_dbiterator_first(dbiterator);
15213 result == ISC_R_SUCCESS;
15214 result = dns_dbiterator_next(dbiterator)) {
15215 result = dns_dbiterator_current(dbiterator, &rawnode, name);
15216 if (result != ISC_R_SUCCESS)
15217 continue;
15218
15219 result = dns_db_findnode(db, name, true, &node);
15220 if (result != ISC_R_SUCCESS)
15221 goto failure;
15222
15223 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
15224 if (result != ISC_R_SUCCESS)
15225 goto failure;
15226
15227 for (result = dns_rdatasetiter_first(rdsit);
15228 result == ISC_R_SUCCESS;
15229 result = dns_rdatasetiter_next(rdsit)) {
15230 dns_rdatasetiter_current(rdsit, &rdataset);
15231 if (rdataset.type == dns_rdatatype_nsec ||
15232 rdataset.type == dns_rdatatype_rrsig ||
15233 rdataset.type == dns_rdatatype_nsec3 ||
15234 rdataset.type == dns_rdatatype_dnskey ||
15235 rdataset.type == dns_rdatatype_nsec3param) {
15236 dns_rdataset_disassociate(&rdataset);
15237 continue;
15238 }
15239 if (rdataset.type == dns_rdatatype_soa &&
15240 have_oldserial) {
15241 result = checkandaddsoa(db, node, version,
15242 &rdataset, oldserial);
15243 } else
15244 result = dns_db_addrdataset(db, node, version,
15245 0, &rdataset, 0,
15246 NULL);
15247 if (result != ISC_R_SUCCESS)
15248 goto failure;
15249
15250 dns_rdataset_disassociate(&rdataset);
15251 }
15252 dns_rdatasetiter_destroy(&rdsit);
15253 dns_db_detachnode(rawdb, &rawnode);
15254 dns_db_detachnode(db, &node);
15255 }
15256
15257 /*
15258 * Call restore_nsec3param() to create private-type records from
15259 * the old nsec3 parameters and insert them into db
15260 */
15261 if (!ISC_LIST_EMPTY(nsec3list)) {
15262 result = restore_nsec3param(zone, db, version, &nsec3list);
15263 if (result != ISC_R_SUCCESS) {
15264 goto failure;
15265 }
15266 }
15267
15268 dns_db_closeversion(db, &version, true);
15269
15270 /*
15271 * Lock hierarchy: zmgr, zone, raw.
15272 */
15273 INSIST(zone != zone->raw);
15274 LOCK_ZONE(zone->raw);
15275 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
15276 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
15277 zone_needdump(zone, 0); /* XXXMPA */
15278 UNLOCK_ZONE(zone->raw);
15279
15280 /*
15281 * Process any queued NSEC3PARAM change requests.
15282 */
15283 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
15284 setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
15285 ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
15286 ev_link);
15287 dummy = NULL;
15288 zone_iattach(zone, &dummy);
15289 isc_task_send(zone->task, &setnsec3param_event);
15290 }
15291
15292 failure:
15293 UNLOCK_ZONE(zone);
15294 if (result != ISC_R_SUCCESS)
15295 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
15296 dns_result_totext(result));
15297
15298 while (!ISC_LIST_EMPTY(nsec3list)) {
15299 nsec3param_t *nsec3p;
15300 nsec3p = ISC_LIST_HEAD(nsec3list);
15301 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
15302 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
15303 }
15304 if (dns_rdataset_isassociated(&rdataset))
15305 dns_rdataset_disassociate(&rdataset);
15306 if (db != NULL) {
15307 if (node != NULL)
15308 dns_db_detachnode(db, &node);
15309 if (version != NULL)
15310 dns_db_closeversion(db, &version, false);
15311 dns_db_detach(&db);
15312 }
15313 if (rawnode != NULL)
15314 dns_db_detachnode(rawdb, &rawnode);
15315 dns_db_detach(&rawdb);
15316 if (dbiterator != NULL)
15317 dns_dbiterator_destroy(&dbiterator);
15318 dns_zone_idetach(&zone);
15319
15320 INSIST(version == NULL);
15321}
15322
15323static isc_result_t
15324zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
15325 isc_event_t *e;
15326 dns_db_t *dummy = NULL;
15327 dns_zone_t *secure = NULL;
15328
15329 e = isc_event_allocate(zone->secure->mctx, zone,
15330 DNS_EVENT_ZONESECUREDB,
15331 receive_secure_db, zone->secure,
15332 sizeof(struct secure_event));
15333 if (e == NULL)
15334 return (ISC_R_NOMEMORY);
15335 dns_db_attach(db, &dummy);
15336 ((struct secure_event *)e)->db = dummy;
15337 INSIST(LOCKED_ZONE(zone->secure));
15338 zone_iattach(zone->secure, &secure);
15339 isc_task_send(zone->secure->task, &e);
15340 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
15341 return (ISC_R_SUCCESS);
15342}
15343
15344isc_result_t
15345dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
15346 isc_result_t result;
15347 dns_zone_t *secure = NULL;
15348
15349 REQUIRE(DNS_ZONE_VALID(zone));
15350 again:
15351 LOCK_ZONE(zone);
15352 if (inline_raw(zone)) {
15353 secure = zone->secure;
15354 INSIST(secure != zone);
15355 TRYLOCK_ZONE(result, secure);
15356 if (result != ISC_R_SUCCESS) {
15357 UNLOCK_ZONE(zone);
15358 secure = NULL;
15359 isc_thread_yield();
15360 goto again;
15361 }
15362 }
15363 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
15364 result = zone_replacedb(zone, db, dump);
15365 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
15366 if (secure != NULL)
15367 UNLOCK_ZONE(secure);
15368 UNLOCK_ZONE(zone);
15369 return (result);
15370}
15371
15372static isc_result_t
15373zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
15374 dns_dbversion_t *ver;
15375 isc_result_t result;
15376 unsigned int soacount = 0;
15377 unsigned int nscount = 0;
15378
15379 /*
15380 * 'zone' and 'zone->db' locked by caller.
15381 */
15382 REQUIRE(DNS_ZONE_VALID(zone));
15383 REQUIRE(LOCKED_ZONE(zone));
15384 if (inline_raw(zone))
15385 REQUIRE(LOCKED_ZONE(zone->secure));
15386
15387 result = zone_get_from_db(zone, db, &nscount, &soacount,
15388 NULL, NULL, NULL, NULL, NULL, NULL);
15389 if (result == ISC_R_SUCCESS) {
15390 if (soacount != 1) {
15391 dns_zone_log(zone, ISC_LOG_ERROR,
15392 "has %d SOA records", soacount);
15393 result = DNS_R_BADZONE;
15394 }
15395 if (nscount == 0 && zone->type != dns_zone_key) {
15396 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
15397 result = DNS_R_BADZONE;
15398 }
15399 if (result != ISC_R_SUCCESS)
15400 return (result);
15401 } else {
15402 dns_zone_log(zone, ISC_LOG_ERROR,
15403 "retrieving SOA and NS records failed: %s",
15404 dns_result_totext(result));
15405 return (result);
15406 }
15407
15408 result = check_nsec3param(zone, db);
15409 if (result != ISC_R_SUCCESS)
15410 return (result);
15411
15412 ver = NULL;
15413 dns_db_currentversion(db, &ver);
15414
15415 /*
15416 * The initial version of a slave zone is always dumped;
15417 * subsequent versions may be journaled instead if this
15418 * is enabled in the configuration.
15419 */
15420 if (zone->db != NULL && zone->journal != NULL &&
15421 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
15422 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
15423 {
15424 uint32_t serial, oldserial;
15425
15426 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
15427
15428 result = dns_db_getsoaserial(db, ver, &serial);
15429 if (result != ISC_R_SUCCESS) {
15430 dns_zone_log(zone, ISC_LOG_ERROR,
15431 "ixfr-from-differences: unable to get "
15432 "new serial");
15433 goto fail;
15434 }
15435
15436 /*
15437 * This is checked in zone_postload() for master zones.
15438 */
15439 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
15440 &oldserial, NULL, NULL, NULL, NULL,
15441 NULL);
15442 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15443 RUNTIME_CHECK(soacount > 0U);
15444 if ((zone->type == dns_zone_slave ||
15445 (zone->type == dns_zone_redirect &&
15446 zone->masters != NULL))
15447 && !isc_serial_gt(serial, oldserial)) {
15448 uint32_t serialmin, serialmax;
15449 serialmin = (oldserial + 1) & 0xffffffffU;
15450 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
15451 dns_zone_log(zone, ISC_LOG_ERROR,
15452 "ixfr-from-differences: failed: "
15453 "new serial (%u) out of range [%u - %u]",
15454 serial, serialmin, serialmax);
15455 result = ISC_R_RANGE;
15456 goto fail;
15457 }
15458
15459 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
15460 zone->journal);
15461 if (result != ISC_R_SUCCESS) {
15462 char strbuf[ISC_STRERRORSIZE];
15463 strerror_r(errno, strbuf, sizeof(strbuf));
15464 dns_zone_log(zone, ISC_LOG_ERROR,
15465 "ixfr-from-differences: failed: "
15466 "%s", strbuf);
15467 goto fallback;
15468 }
15469 if (dump)
15470 zone_needdump(zone, DNS_DUMP_DELAY);
15471 else
15472 zone_journal_compact(zone, zone->db, serial);
15473 if (zone->type == dns_zone_master && inline_raw(zone))
15474 zone_send_secureserial(zone, serial);
15475 } else {
15476 fallback:
15477 if (dump && zone->masterfile != NULL) {
15478 /*
15479 * If DNS_ZONEFLG_FORCEXFER was set we don't want
15480 * to keep the old masterfile.
15481 */
15482 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
15483 remove(zone->masterfile) < 0 && errno != ENOENT) {
15484 char strbuf[ISC_STRERRORSIZE];
15485 strerror_r(errno, strbuf, sizeof(strbuf));
15486 isc_log_write(dns_lctx,
15487 DNS_LOGCATEGORY_GENERAL,
15488 DNS_LOGMODULE_ZONE,
15489 ISC_LOG_WARNING,
15490 "unable to remove masterfile "
15491 "'%s': '%s'",
15492 zone->masterfile, strbuf);
15493 }
15494 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
15495 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
15496 else
15497 zone_needdump(zone, 0);
15498 }
15499 if (dump && zone->journal != NULL) {
15500 /*
15501 * The in-memory database just changed, and
15502 * because 'dump' is set, it didn't change by
15503 * being loaded from disk. Also, we have not
15504 * journaled diffs for this change.
15505 * Therefore, the on-disk journal is missing
15506 * the deltas for this change. Since it can
15507 * no longer be used to bring the zone
15508 * up-to-date, it is useless and should be
15509 * removed.
15510 */
15511 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15512 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15513 "removing journal file");
15514 if (remove(zone->journal) < 0 && errno != ENOENT) {
15515 char strbuf[ISC_STRERRORSIZE];
15516 strerror_r(errno, strbuf, sizeof(strbuf));
15517 isc_log_write(dns_lctx,
15518 DNS_LOGCATEGORY_GENERAL,
15519 DNS_LOGMODULE_ZONE,
15520 ISC_LOG_WARNING,
15521 "unable to remove journal "
15522 "'%s': '%s'",
15523 zone->journal, strbuf);
15524 }
15525 }
15526
15527 if (inline_raw(zone))
15528 zone_send_securedb(zone, db);
15529 }
15530
15531 dns_db_closeversion(db, &ver, false);
15532
15533 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
15534
15535 if (zone->db != NULL)
15536 zone_detachdb(zone);
15537 zone_attachdb(zone, db);
15538 dns_db_settask(zone->db, zone->task);
15539 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
15540 return (ISC_R_SUCCESS);
15541
15542 fail:
15543 dns_db_closeversion(db, &ver, false);
15544 return (result);
15545}
15546
15547/* The caller must hold the dblock as a writer. */
15548static inline void
15549zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
15550 REQUIRE(zone->db == NULL && db != NULL);
15551
15552 dns_db_attach(db, &zone->db);
15553}
15554
15555/* The caller must hold the dblock as a writer. */
15556static inline void
15557zone_detachdb(dns_zone_t *zone) {
15558 REQUIRE(zone->db != NULL);
15559
15560 dns_db_detach(&zone->db);
15561}
15562
15563static void
15564zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
15565 isc_time_t now;
15566 bool again = false;
15567 unsigned int soacount;
15568 unsigned int nscount;
15569 uint32_t serial, refresh, retry, expire, minimum;
15570 isc_result_t xfrresult = result;
15571 bool free_needed;
15572 dns_zone_t *secure = NULL;
15573
15574 REQUIRE(DNS_ZONE_VALID(zone));
15575
15576 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15577 "zone transfer finished: %s", dns_result_totext(result));
15578
15579 /*
15580 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
15581 * could result in a deadlock due to a LOR so we will spin if we
15582 * can't obtain the both locks.
15583 */
15584 again:
15585 LOCK_ZONE(zone);
15586 if (inline_raw(zone)) {
15587 secure = zone->secure;
15588 INSIST(secure != zone);
15589 TRYLOCK_ZONE(result, secure);
15590 if (result != ISC_R_SUCCESS) {
15591 UNLOCK_ZONE(zone);
15592 secure = NULL;
15593 isc_thread_yield();
15594 goto again;
15595 }
15596 }
15597
15598 INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
15599 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15600 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
15601
15602 TIME_NOW(&now);
15603 switch (xfrresult) {
15604 case ISC_R_SUCCESS:
15605 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
15606 /* FALLTHROUGH */
15607 case DNS_R_UPTODATE:
15608 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
15609 /*
15610 * Has the zone expired underneath us?
15611 */
15612 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15613 if (zone->db == NULL) {
15614 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15615 goto same_master;
15616 }
15617
15618 /*
15619 * Update the zone structure's data from the actual
15620 * SOA received.
15621 */
15622 nscount = 0;
15623 soacount = 0;
15624 INSIST(zone->db != NULL);
15625 result = zone_get_from_db(zone, zone->db, &nscount,
15626 &soacount, &serial, &refresh,
15627 &retry, &expire, &minimum, NULL);
15628 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15629 if (result == ISC_R_SUCCESS) {
15630 if (soacount != 1)
15631 dns_zone_log(zone, ISC_LOG_ERROR,
15632 "transferred zone "
15633 "has %d SOA record%s", soacount,
15634 (soacount != 0) ? "s" : "");
15635 if (nscount == 0) {
15636 dns_zone_log(zone, ISC_LOG_ERROR,
15637 "transferred zone "
15638 "has no NS records");
15639 if (DNS_ZONE_FLAG(zone,
15640 DNS_ZONEFLG_HAVETIMERS)) {
15641 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
15642 zone->retry = DNS_ZONE_DEFAULTRETRY;
15643 }
15644 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
15645 zone_unload(zone);
15646 goto next_master;
15647 }
15648 zone->refresh = RANGE(refresh, zone->minrefresh,
15649 zone->maxrefresh);
15650 zone->retry = RANGE(retry, zone->minretry,
15651 zone->maxretry);
15652 zone->expire = RANGE(expire,
15653 zone->refresh + zone->retry,
15654 DNS_MAX_EXPIRE);
15655 zone->minimum = minimum;
15656 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
15657 }
15658
15659 /*
15660 * Set our next update/expire times.
15661 */
15662 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
15663 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15664 zone->refreshtime = now;
15665 DNS_ZONE_TIME_ADD(&now, zone->expire,
15666 &zone->expiretime);
15667 } else {
15668 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
15669 &zone->refreshtime);
15670 DNS_ZONE_TIME_ADD(&now, zone->expire,
15671 &zone->expiretime);
15672 }
15673 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
15674 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
15675 if (zone->tsigkey != NULL) {
15676 char namebuf[DNS_NAME_FORMATSIZE];
15677 dns_name_format(&zone->tsigkey->name, namebuf,
15678 sizeof(namebuf));
15679 snprintf(buf, sizeof(buf), ": TSIG '%s'",
15680 namebuf);
15681 } else
15682 buf[0] = '\0';
15683 dns_zone_log(zone, ISC_LOG_INFO,
15684 "transferred serial %u%s",
15685 serial, buf);
15686 if (inline_raw(zone))
15687 zone_send_secureserial(zone, serial);
15688 }
15689
15690 /*
15691 * This is not necessary if we just performed a AXFR
15692 * however it is necessary for an IXFR / UPTODATE and
15693 * won't hurt with an AXFR.
15694 */
15695 if (zone->masterfile != NULL || zone->journal != NULL) {
15696 unsigned int delay = DNS_DUMP_DELAY;
15697
15698 result = ISC_R_FAILURE;
15699 if (zone->journal != NULL)
15700 result = isc_file_settime(zone->journal, &now);
15701 if (result != ISC_R_SUCCESS &&
15702 zone->masterfile != NULL)
15703 result = isc_file_settime(zone->masterfile,
15704 &now);
15705
15706 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
15707 result == ISC_R_FILENOTFOUND)
15708 delay = 0;
15709
15710 if ((result == ISC_R_SUCCESS ||
15711 result == ISC_R_FILENOTFOUND) &&
15712 zone->masterfile != NULL)
15713 zone_needdump(zone, delay);
15714 else if (result != ISC_R_SUCCESS)
15715 dns_zone_log(zone, ISC_LOG_ERROR,
15716 "transfer: could not set file "
15717 "modification time of '%s': %s",
15718 zone->masterfile,
15719 dns_result_totext(result));
15720 }
15721 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
15722 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
15723 break;
15724
15725 case DNS_R_BADIXFR:
15726 /* Force retry with AXFR. */
15727 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
15728 goto same_master;
15729
15730 case DNS_R_TOOMANYRECORDS:
15731 case DNS_R_VERIFYFAILURE:
15732 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
15733 inc_stats(zone, dns_zonestatscounter_xfrfail);
15734 break;
15735
15736 default:
15737 next_master:
15738 /*
15739 * Skip to next failed / untried master.
15740 */
15741 do {
15742 zone->curmaster++;
15743 } while (zone->curmaster < zone->masterscnt &&
15744 zone->mastersok[zone->curmaster]);
15745 /* FALLTHROUGH */
15746 same_master:
15747 if (zone->curmaster >= zone->masterscnt) {
15748 zone->curmaster = 0;
15749 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
15750 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
15751 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
15752 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
15753 while (zone->curmaster < zone->masterscnt &&
15754 zone->mastersok[zone->curmaster])
15755 zone->curmaster++;
15756 again = true;
15757 } else
15758 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
15759 } else {
15760 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
15761 again = true;
15762 }
15763 inc_stats(zone, dns_zonestatscounter_xfrfail);
15764 break;
15765 }
15766 zone_settimer(zone, &now);
15767
15768 /*
15769 * If creating the transfer object failed, zone->xfr is NULL.
15770 * Otherwise, we are called as the done callback of a zone
15771 * transfer object that just entered its shutting-down
15772 * state. Since we are no longer responsible for shutting
15773 * it down, we can detach our reference.
15774 */
15775 if (zone->xfr != NULL)
15776 dns_xfrin_detach(&zone->xfr);
15777
15778 if (zone->tsigkey != NULL)
15779 dns_tsigkey_detach(&zone->tsigkey);
15780
15781 /*
15782 * Handle any deferred journal compaction.
15783 */
15784 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
15785 dns_db_t *db = NULL;
15786 if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
15787 zone_journal_compact(zone, db, zone->compact_serial);
15788 dns_db_detach(&db);
15789 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
15790 }
15791 }
15792
15793 if (secure != NULL)
15794 UNLOCK_ZONE(secure);
15795 /*
15796 * This transfer finishing freed up a transfer quota slot.
15797 * Let any other zones waiting for quota have it.
15798 */
15799 if (zone->zmgr != NULL &&
15800 zone->statelist == &zone->zmgr->xfrin_in_progress) {
15801 UNLOCK_ZONE(zone);
15802 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15803 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
15804 zone->statelist = NULL;
15805 zmgr_resume_xfrs(zone->zmgr, false);
15806 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15807 LOCK_ZONE(zone);
15808 }
15809
15810 /*
15811 * Retry with a different server if necessary.
15812 */
15813 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
15814 queue_soa_query(zone);
15815
15816 INSIST(zone->irefs > 0);
15817 zone->irefs--;
15818 free_needed = exit_check(zone);
15819 UNLOCK_ZONE(zone);
15820 if (free_needed)
15821 zone_free(zone);
15822}
15823
15824static void
15825zone_loaddone(void *arg, isc_result_t result) {
15826 static char me[] = "zone_loaddone";
15827 dns_load_t *load = arg;
15828 dns_zone_t *zone;
15829 isc_result_t tresult;
15830 dns_zone_t *secure = NULL;
15831
15832 REQUIRE(DNS_LOAD_VALID(load));
15833 zone = load->zone;
15834
15835 ENTER;
15836
15837 /*
15838 * If zone loading failed, remove the update db callbacks prior
15839 * to calling the list of callbacks in the zone load structure.
15840 */
15841 if (result != ISC_R_SUCCESS) {
15842 dns_zone_rpz_disable_db(zone, load->db);
15843 dns_zone_catz_disable_db(zone, load->db);
15844 }
15845
15846 tresult = dns_db_endload(load->db, &load->callbacks);
15847 if (tresult != ISC_R_SUCCESS &&
15848 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
15849 result = tresult;
15850
15851 /*
15852 * Lock hierarchy: zmgr, zone, raw.
15853 */
15854 again:
15855 LOCK_ZONE(zone);
15856 INSIST(zone != zone->raw);
15857 if (inline_secure(zone))
15858 LOCK_ZONE(zone->raw);
15859 else if (inline_raw(zone)) {
15860 secure = zone->secure;
15861 TRYLOCK_ZONE(result, secure);
15862 if (result != ISC_R_SUCCESS) {
15863 UNLOCK_ZONE(zone);
15864 secure = NULL;
15865 isc_thread_yield();
15866 goto again;
15867 }
15868 }
15869 (void)zone_postload(zone, load->db, load->loadtime, result);
15870 zonemgr_putio(&zone->readio);
15871 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
15872 zone_idetach(&load->callbacks.zone);
15873 /*
15874 * Leave the zone frozen if the reload fails.
15875 */
15876 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
15877 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
15878 zone->update_disabled = false;
15879 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
15880 if (inline_secure(zone))
15881 UNLOCK_ZONE(zone->raw);
15882 else if (secure != NULL)
15883 UNLOCK_ZONE(secure);
15884 UNLOCK_ZONE(zone);
15885
15886 load->magic = 0;
15887 dns_db_detach(&load->db);
15888 if (load->zone->lctx != NULL)
15889 dns_loadctx_detach(&load->zone->lctx);
15890 dns_zone_idetach(&load->zone);
15891 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
15892}
15893
15894void
15895dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
15896 REQUIRE(DNS_ZONE_VALID(zone));
15897 REQUIRE(table != NULL);
15898 REQUIRE(*table == NULL);
15899
15900 LOCK_ZONE(zone);
15901 if (zone->ssutable != NULL)
15902 dns_ssutable_attach(zone->ssutable, table);
15903 UNLOCK_ZONE(zone);
15904}
15905
15906void
15907dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
15908 REQUIRE(DNS_ZONE_VALID(zone));
15909
15910 LOCK_ZONE(zone);
15911 if (zone->ssutable != NULL)
15912 dns_ssutable_detach(&zone->ssutable);
15913 if (table != NULL)
15914 dns_ssutable_attach(table, &zone->ssutable);
15915 UNLOCK_ZONE(zone);
15916}
15917
15918void
15919dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
15920 REQUIRE(DNS_ZONE_VALID(zone));
15921
15922 zone->sigvalidityinterval = interval;
15923}
15924
15925uint32_t
15926dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
15927 REQUIRE(DNS_ZONE_VALID(zone));
15928
15929 return (zone->sigvalidityinterval);
15930}
15931
15932void
15933dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
15934 REQUIRE(DNS_ZONE_VALID(zone));
15935
15936 zone->keyvalidityinterval = interval;
15937}
15938
15939uint32_t
15940dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
15941 REQUIRE(DNS_ZONE_VALID(zone));
15942
15943 return (zone->keyvalidityinterval);
15944}
15945
15946void
15947dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
15948 isc_time_t now;
15949
15950 REQUIRE(DNS_ZONE_VALID(zone));
15951
15952 LOCK_ZONE(zone);
15953 zone->sigresigninginterval = interval;
15954 set_resigntime(zone);
15955 if (zone->task != NULL) {
15956 TIME_NOW(&now);
15957 zone_settimer(zone, &now);
15958 }
15959 UNLOCK_ZONE(zone);
15960}
15961
15962uint32_t
15963dns_zone_getsigresigninginterval(dns_zone_t *zone) {
15964 REQUIRE(DNS_ZONE_VALID(zone));
15965
15966 return (zone->sigresigninginterval);
15967}
15968
15969static void
15970queue_xfrin(dns_zone_t *zone) {
15971 const char me[] = "queue_xfrin";
15972 isc_result_t result;
15973 dns_zonemgr_t *zmgr = zone->zmgr;
15974
15975 ENTER;
15976
15977 INSIST(zone->statelist == NULL);
15978
15979 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15980 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
15981 LOCK_ZONE(zone);
15982 zone->irefs++;
15983 UNLOCK_ZONE(zone);
15984 zone->statelist = &zmgr->waiting_for_xfrin;
15985 result = zmgr_start_xfrin_ifquota(zmgr, zone);
15986 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15987
15988 if (result == ISC_R_QUOTA) {
15989 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
15990 "zone transfer deferred due to quota");
15991 } else if (result != ISC_R_SUCCESS) {
15992 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
15993 "starting zone transfer: %s",
15994 isc_result_totext(result));
15995 }
15996}
15997
15998/*
15999 * This event callback is called when a zone has received
16000 * any necessary zone transfer quota. This is the time
16001 * to go ahead and start the transfer.
16002 */
16003static void
16004got_transfer_quota(isc_task_t *task, isc_event_t *event) {
16005 isc_result_t result = ISC_R_SUCCESS;
16006 dns_peer_t *peer = NULL;
16007 char master[ISC_SOCKADDR_FORMATSIZE];
16008 char source[ISC_SOCKADDR_FORMATSIZE];
16009 dns_rdatatype_t xfrtype;
16010 dns_zone_t *zone = event->ev_arg;
16011 isc_netaddr_t masterip;
16012 isc_sockaddr_t sourceaddr;
16013 isc_sockaddr_t masteraddr;
16014 isc_time_t now;
16015 const char *soa_before = "";
16016 isc_dscp_t dscp = -1;
16017 bool loaded;
16018
16019 UNUSED(task);
16020
16021 INSIST(task == zone->task);
16022
16023 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
16024 result = ISC_R_CANCELED;
16025 goto cleanup;
16026 }
16027
16028 TIME_NOW(&now);
16029
16030 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
16031 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
16032 &zone->sourceaddr, &now))
16033 {
16034 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
16035 dns_zone_log(zone, ISC_LOG_INFO,
16036 "got_transfer_quota: skipping zone transfer as "
16037 "master %s (source %s) is unreachable (cached)",
16038 master, source);
16039 result = ISC_R_CANCELED;
16040 goto cleanup;
16041 }
16042
16043 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
16044 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
16045
16046 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
16047 soa_before = "SOA before ";
16048 /*
16049 * Decide whether we should request IXFR or AXFR.
16050 */
16051 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16052 loaded = (zone->db != NULL);
16053 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16054
16055 if (!loaded) {
16056 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16057 "no database exists yet, requesting AXFR of "
16058 "initial version from %s", master);
16059 xfrtype = dns_rdatatype_axfr;
16060 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
16061 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16062 "forced reload, requesting AXFR of "
16063 "initial version from %s", master);
16064 xfrtype = dns_rdatatype_axfr;
16065 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
16066 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16067 "retrying with AXFR from %s due to "
16068 "previous IXFR failure", master);
16069 xfrtype = dns_rdatatype_axfr;
16070 LOCK_ZONE(zone);
16071 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
16072 UNLOCK_ZONE(zone);
16073 } else {
16074 bool use_ixfr = true;
16075 if (peer != NULL)
16076 result = dns_peer_getrequestixfr(peer, &use_ixfr);
16077 if (peer == NULL || result != ISC_R_SUCCESS)
16078 use_ixfr = zone->requestixfr;
16079 if (use_ixfr == false) {
16080 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16081 "IXFR disabled, requesting %sAXFR from %s",
16082 soa_before, master);
16083 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
16084 xfrtype = dns_rdatatype_soa;
16085 else
16086 xfrtype = dns_rdatatype_axfr;
16087 } else {
16088 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16089 "requesting IXFR from %s", master);
16090 xfrtype = dns_rdatatype_ixfr;
16091 }
16092 }
16093
16094 /*
16095 * Determine if we should attempt to sign the request with TSIG.
16096 */
16097 result = ISC_R_NOTFOUND;
16098
16099 /*
16100 * First, look for a tsig key in the master statement, then
16101 * try for a server key.
16102 */
16103 if ((zone->masterkeynames != NULL) &&
16104 (zone->masterkeynames[zone->curmaster] != NULL)) {
16105 dns_view_t *view = dns_zone_getview(zone);
16106 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
16107 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
16108 }
16109 if (zone->tsigkey == NULL)
16110 result = dns_view_getpeertsig(zone->view, &masterip,
16111 &zone->tsigkey);
16112
16113 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16114 dns_zone_log(zone, ISC_LOG_ERROR,
16115 "could not get TSIG key for zone transfer: %s",
16116 isc_result_totext(result));
16117 }
16118
16119 if (zone->masterdscps != NULL)
16120 dscp = zone->masterdscps[zone->curmaster];
16121
16122 LOCK_ZONE(zone);
16123 masteraddr = zone->masteraddr;
16124 sourceaddr = zone->sourceaddr;
16125 switch (isc_sockaddr_pf(&masteraddr)) {
16126 case PF_INET:
16127 if (dscp == -1)
16128 dscp = zone->xfrsource4dscp;
16129 break;
16130 case PF_INET6:
16131 if (dscp == -1)
16132 dscp = zone->xfrsource6dscp;
16133 break;
16134 default:
16135 INSIST(0);
16136 ISC_UNREACHABLE();
16137 }
16138 UNLOCK_ZONE(zone);
16139 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
16140 result = dns_xfrin_create(zone, xfrtype, &masteraddr, &sourceaddr,
16141 dscp, zone->tsigkey, zone->mctx,
16142 zone->zmgr->timermgr, zone->zmgr->socketmgr,
16143 zone->task, zone_xfrdone, &zone->xfr);
16144 if (result == ISC_R_SUCCESS) {
16145 LOCK_ZONE(zone);
16146 if (xfrtype == dns_rdatatype_axfr) {
16147 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
16148 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
16149 else
16150 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
16151 } else if (xfrtype == dns_rdatatype_ixfr) {
16152 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
16153 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
16154 else
16155 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
16156 }
16157 UNLOCK_ZONE(zone);
16158 }
16159 cleanup:
16160 /*
16161 * Any failure in this function is handled like a failed
16162 * zone transfer. This ensures that we get removed from
16163 * zmgr->xfrin_in_progress.
16164 */
16165 if (result != ISC_R_SUCCESS)
16166 zone_xfrdone(zone, result);
16167
16168 isc_event_free(&event);
16169}
16170
16171/*
16172 * Update forwarding support.
16173 */
16174
16175static void
16176forward_destroy(dns_forward_t *forward) {
16177
16178 forward->magic = 0;
16179 if (forward->request != NULL)
16180 dns_request_destroy(&forward->request);
16181 if (forward->msgbuf != NULL)
16182 isc_buffer_free(&forward->msgbuf);
16183 if (forward->zone != NULL) {
16184 LOCK(&forward->zone->lock);
16185 if (ISC_LINK_LINKED(forward, link))
16186 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
16187 UNLOCK(&forward->zone->lock);
16188 dns_zone_idetach(&forward->zone);
16189 }
16190 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
16191}
16192
16193static isc_result_t
16194sendtomaster(dns_forward_t *forward) {
16195 isc_result_t result;
16196 isc_sockaddr_t src;
16197 isc_dscp_t dscp = -1;
16198
16199 LOCK_ZONE(forward->zone);
16200
16201 if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
16202 UNLOCK_ZONE(forward->zone);
16203 return (ISC_R_CANCELED);
16204 }
16205
16206 if (forward->which >= forward->zone->masterscnt) {
16207 UNLOCK_ZONE(forward->zone);
16208 return (ISC_R_NOMORE);
16209 }
16210
16211 forward->addr = forward->zone->masters[forward->which];
16212 /*
16213 * Always use TCP regardless of whether the original update
16214 * used TCP.
16215 * XXX The timeout may but a bit small if we are far down a
16216 * transfer graph and the master has to try several masters.
16217 */
16218 switch (isc_sockaddr_pf(&forward->addr)) {
16219 case PF_INET:
16220 src = forward->zone->xfrsource4;
16221 dscp = forward->zone->xfrsource4dscp;
16222 break;
16223 case PF_INET6:
16224 src = forward->zone->xfrsource6;
16225 dscp = forward->zone->xfrsource6dscp;
16226 break;
16227 default:
16228 result = ISC_R_NOTIMPLEMENTED;
16229 goto unlock;
16230 }
16231 result = dns_request_createraw(forward->zone->view->requestmgr,
16232 forward->msgbuf,
16233 &src, &forward->addr, dscp,
16234 forward->options, 15 /* XXX */,
16235 0, 0, forward->zone->task,
16236 forward_callback, forward,
16237 &forward->request);
16238 if (result == ISC_R_SUCCESS) {
16239 if (!ISC_LINK_LINKED(forward, link))
16240 ISC_LIST_APPEND(forward->zone->forwards, forward, link);
16241 }
16242
16243 unlock:
16244 UNLOCK_ZONE(forward->zone);
16245 return (result);
16246}
16247
16248static void
16249forward_callback(isc_task_t *task, isc_event_t *event) {
16250 const char me[] = "forward_callback";
16251 dns_requestevent_t *revent = (dns_requestevent_t *)event;
16252 dns_message_t *msg = NULL;
16253 char master[ISC_SOCKADDR_FORMATSIZE];
16254 isc_result_t result;
16255 dns_forward_t *forward;
16256 dns_zone_t *zone;
16257
16258 UNUSED(task);
16259
16260 forward = revent->ev_arg;
16261 INSIST(DNS_FORWARD_VALID(forward));
16262 zone = forward->zone;
16263 INSIST(DNS_ZONE_VALID(zone));
16264
16265 ENTER;
16266
16267 isc_sockaddr_format(&forward->addr, master, sizeof(master));
16268
16269 if (revent->result != ISC_R_SUCCESS) {
16270 dns_zone_log(zone, ISC_LOG_INFO,
16271 "could not forward dynamic update to %s: %s",
16272 master, dns_result_totext(revent->result));
16273 goto next_master;
16274 }
16275
16276 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
16277 if (result != ISC_R_SUCCESS)
16278 goto next_master;
16279
16280 result = dns_request_getresponse(revent->request, msg,
16281 DNS_MESSAGEPARSE_PRESERVEORDER |
16282 DNS_MESSAGEPARSE_CLONEBUFFER);
16283 if (result != ISC_R_SUCCESS)
16284 goto next_master;
16285
16286 switch (msg->rcode) {
16287 /*
16288 * Pass these rcodes back to client.
16289 */
16290 case dns_rcode_noerror:
16291 case dns_rcode_yxdomain:
16292 case dns_rcode_yxrrset:
16293 case dns_rcode_nxrrset:
16294 case dns_rcode_refused:
16295 case dns_rcode_nxdomain: {
16296 char rcode[128];
16297 isc_buffer_t rb;
16298
16299 isc_buffer_init(&rb, rcode, sizeof(rcode));
16300 (void)dns_rcode_totext(msg->rcode, &rb);
16301 dns_zone_log(zone, ISC_LOG_INFO,
16302 "forwarded dynamic update: "
16303 "master %s returned: %.*s",
16304 master, (int)rb.used, rcode);
16305 break;
16306 }
16307
16308 /* These should not occur if the masters/zone are valid. */
16309 case dns_rcode_notzone:
16310 case dns_rcode_notauth: {
16311 char rcode[128];
16312 isc_buffer_t rb;
16313
16314 isc_buffer_init(&rb, rcode, sizeof(rcode));
16315 (void)dns_rcode_totext(msg->rcode, &rb);
16316 dns_zone_log(zone, ISC_LOG_WARNING,
16317 "forwarding dynamic update: "
16318 "unexpected response: master %s returned: %.*s",
16319 master, (int)rb.used, rcode);
16320 goto next_master;
16321 }
16322
16323 /* Try another server for these rcodes. */
16324 case dns_rcode_formerr:
16325 case dns_rcode_servfail:
16326 case dns_rcode_notimp:
16327 case dns_rcode_badvers:
16328 default:
16329 goto next_master;
16330 }
16331
16332 /* call callback */
16333 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
16334 msg = NULL;
16335 dns_request_destroy(&forward->request);
16336 forward_destroy(forward);
16337 isc_event_free(&event);
16338 return;
16339
16340 next_master:
16341 if (msg != NULL)
16342 dns_message_destroy(&msg);
16343 isc_event_free(&event);
16344 forward->which++;
16345 dns_request_destroy(&forward->request);
16346 result = sendtomaster(forward);
16347 if (result != ISC_R_SUCCESS) {
16348 /* call callback */
16349 dns_zone_log(zone, ISC_LOG_DEBUG(3),
16350 "exhausted dynamic update forwarder list");
16351 (forward->callback)(forward->callback_arg, result, NULL);
16352 forward_destroy(forward);
16353 }
16354}
16355
16356isc_result_t
16357dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
16358 dns_updatecallback_t callback, void *callback_arg)
16359{
16360 dns_forward_t *forward;
16361 isc_result_t result;
16362 isc_region_t *mr;
16363
16364 REQUIRE(DNS_ZONE_VALID(zone));
16365 REQUIRE(msg != NULL);
16366 REQUIRE(callback != NULL);
16367
16368 forward = isc_mem_get(zone->mctx, sizeof(*forward));
16369 if (forward == NULL)
16370 return (ISC_R_NOMEMORY);
16371
16372 forward->request = NULL;
16373 forward->zone = NULL;
16374 forward->msgbuf = NULL;
16375 forward->which = 0;
16376 forward->mctx = 0;
16377 forward->callback = callback;
16378 forward->callback_arg = callback_arg;
16379 ISC_LINK_INIT(forward, link);
16380 forward->magic = FORWARD_MAGIC;
16381 forward->options = DNS_REQUESTOPT_TCP;
16382 /*
16383 * If we have a SIG(0) signed message we need to preserve the
16384 * query id as that is included in the SIG(0) computation.
16385 */
16386 if (msg->sig0 != NULL)
16387 forward->options |= DNS_REQUESTOPT_FIXEDID;
16388
16389 mr = dns_message_getrawmessage(msg);
16390 if (mr == NULL) {
16391 result = ISC_R_UNEXPECTEDEND;
16392 goto cleanup;
16393 }
16394
16395 result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
16396 if (result != ISC_R_SUCCESS)
16397 goto cleanup;
16398 result = isc_buffer_copyregion(forward->msgbuf, mr);
16399 if (result != ISC_R_SUCCESS)
16400 goto cleanup;
16401
16402 isc_mem_attach(zone->mctx, &forward->mctx);
16403 dns_zone_iattach(zone, &forward->zone);
16404 result = sendtomaster(forward);
16405
16406 cleanup:
16407 if (result != ISC_R_SUCCESS) {
16408 forward_destroy(forward);
16409 }
16410 return (result);
16411}
16412
16413isc_result_t
16414dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
16415 REQUIRE(DNS_ZONE_VALID(zone));
16416 REQUIRE(next != NULL && *next == NULL);
16417
16418 *next = ISC_LIST_NEXT(zone, link);
16419 if (*next == NULL)
16420 return (ISC_R_NOMORE);
16421 else
16422 return (ISC_R_SUCCESS);
16423}
16424
16425isc_result_t
16426dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
16427 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16428 REQUIRE(first != NULL && *first == NULL);
16429
16430 *first = ISC_LIST_HEAD(zmgr->zones);
16431 if (*first == NULL)
16432 return (ISC_R_NOMORE);
16433 else
16434 return (ISC_R_SUCCESS);
16435}
16436
16437/***
16438 *** Zone manager.
16439 ***/
16440
16441isc_result_t
16442dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
16443 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
16444 dns_zonemgr_t **zmgrp)
16445{
16446 dns_zonemgr_t *zmgr;
16447 isc_result_t result;
16448
16449 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
16450 if (zmgr == NULL)
16451 return (ISC_R_NOMEMORY);
16452 zmgr->mctx = NULL;
16453 zmgr->refs = 1;
16454 isc_mem_attach(mctx, &zmgr->mctx);
16455 zmgr->taskmgr = taskmgr;
16456 zmgr->timermgr = timermgr;
16457 zmgr->socketmgr = socketmgr;
16458 zmgr->zonetasks = NULL;
16459 zmgr->loadtasks = NULL;
16460 zmgr->mctxpool = NULL;
16461 zmgr->task = NULL;
16462 zmgr->notifyrl = NULL;
16463 zmgr->refreshrl = NULL;
16464 zmgr->startupnotifyrl = NULL;
16465 zmgr->startuprefreshrl = NULL;
16466 ISC_LIST_INIT(zmgr->zones);
16467 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
16468 ISC_LIST_INIT(zmgr->xfrin_in_progress);
16469 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
16470 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
16471 if (result != ISC_R_SUCCESS)
16472 goto free_mem;
16473
16474 zmgr->transfersin = 10;
16475 zmgr->transfersperns = 2;
16476
16477 /* Unreachable lock. */
16478 result = isc_rwlock_init(&zmgr->urlock, 0, 0);
16479 if (result != ISC_R_SUCCESS)
16480 goto free_rwlock;
16481
16482 /* Create a single task for queueing of SOA queries. */
16483 result = isc_task_create(taskmgr, 1, &zmgr->task);
16484 if (result != ISC_R_SUCCESS)
16485 goto free_urlock;
16486
16487 isc_task_setname(zmgr->task, "zmgr", zmgr);
16488 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16489 &zmgr->notifyrl);
16490 if (result != ISC_R_SUCCESS)
16491 goto free_task;
16492
16493 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16494 &zmgr->refreshrl);
16495 if (result != ISC_R_SUCCESS)
16496 goto free_notifyrl;
16497
16498 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16499 &zmgr->startupnotifyrl);
16500 if (result != ISC_R_SUCCESS)
16501 goto free_refreshrl;
16502
16503 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16504 &zmgr->startuprefreshrl);
16505 if (result != ISC_R_SUCCESS)
16506 goto free_startupnotifyrl;
16507
16508 /* default to 20 refresh queries / notifies per second. */
16509 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
16510 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
16511 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
16512 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
16513 isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
16514 isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
16515
16516 zmgr->iolimit = 1;
16517 zmgr->ioactive = 0;
16518 ISC_LIST_INIT(zmgr->high);
16519 ISC_LIST_INIT(zmgr->low);
16520
16521 isc_mutex_init(&zmgr->iolock);
16522
16523 zmgr->magic = ZONEMGR_MAGIC;
16524
16525 *zmgrp = zmgr;
16526 return (ISC_R_SUCCESS);
16527
16528#if 0
16529 free_iolock:
16530 isc_mutex_destroy(&zmgr->iolock);
16531#endif
16532 free_startupnotifyrl:
16533 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
16534 free_refreshrl:
16535 isc_ratelimiter_detach(&zmgr->refreshrl);
16536 free_notifyrl:
16537 isc_ratelimiter_detach(&zmgr->notifyrl);
16538 free_task:
16539 isc_task_detach(&zmgr->task);
16540 free_urlock:
16541 isc_rwlock_destroy(&zmgr->urlock);
16542 free_rwlock:
16543 isc_rwlock_destroy(&zmgr->rwlock);
16544 free_mem:
16545 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
16546 isc_mem_detach(&mctx);
16547 return (result);
16548}
16549
16550isc_result_t
16551dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
16552 isc_result_t result;
16553 isc_mem_t *mctx = NULL;
16554 dns_zone_t *zone = NULL;
16555 void *item;
16556
16557 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16558 REQUIRE(zonep != NULL && *zonep == NULL);
16559
16560 if (zmgr->mctxpool == NULL)
16561 return (ISC_R_FAILURE);
16562
16563 item = isc_pool_get(zmgr->mctxpool);
16564 if (item == NULL)
16565 return (ISC_R_FAILURE);
16566
16567 isc_mem_attach((isc_mem_t *) item, &mctx);
16568 result = dns_zone_create(&zone, mctx);
16569 isc_mem_detach(&mctx);
16570
16571 if (result == ISC_R_SUCCESS)
16572 *zonep = zone;
16573
16574 return (result);
16575}
16576
16577isc_result_t
16578dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16579 isc_result_t result;
16580
16581 REQUIRE(DNS_ZONE_VALID(zone));
16582 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16583
16584 if (zmgr->zonetasks == NULL)
16585 return (ISC_R_FAILURE);
16586
16587 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16588 LOCK_ZONE(zone);
16589 REQUIRE(zone->task == NULL);
16590 REQUIRE(zone->timer == NULL);
16591 REQUIRE(zone->zmgr == NULL);
16592
16593 isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
16594 isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
16595
16596 /*
16597 * Set the task name. The tag will arbitrarily point to one
16598 * of the zones sharing the task (in practice, the one
16599 * to be managed last).
16600 */
16601 isc_task_setname(zone->task, "zone", zone);
16602 isc_task_setname(zone->loadtask, "loadzone", zone);
16603
16604 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
16605 NULL, NULL,
16606 zone->task, zone_timer, zone,
16607 &zone->timer);
16608
16609 if (result != ISC_R_SUCCESS)
16610 goto cleanup_tasks;
16611
16612 /*
16613 * The timer "holds" a iref.
16614 */
16615 zone->irefs++;
16616 INSIST(zone->irefs != 0);
16617
16618 ISC_LIST_APPEND(zmgr->zones, zone, link);
16619 zone->zmgr = zmgr;
16620 zmgr->refs++;
16621
16622 goto unlock;
16623
16624 cleanup_tasks:
16625 isc_task_detach(&zone->loadtask);
16626 isc_task_detach(&zone->task);
16627
16628 unlock:
16629 UNLOCK_ZONE(zone);
16630 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16631 return (result);
16632}
16633
16634void
16635dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16636 bool free_now = false;
16637
16638 REQUIRE(DNS_ZONE_VALID(zone));
16639 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16640 REQUIRE(zone->zmgr == zmgr);
16641
16642 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16643 LOCK_ZONE(zone);
16644
16645 ISC_LIST_UNLINK(zmgr->zones, zone, link);
16646 zone->zmgr = NULL;
16647 zmgr->refs--;
16648 if (zmgr->refs == 0)
16649 free_now = true;
16650
16651 UNLOCK_ZONE(zone);
16652 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16653
16654 if (free_now)
16655 zonemgr_free(zmgr);
16656 ENSURE(zone->zmgr == NULL);
16657}
16658
16659void
16660dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
16661 REQUIRE(DNS_ZONEMGR_VALID(source));
16662 REQUIRE(target != NULL && *target == NULL);
16663
16664 RWLOCK(&source->rwlock, isc_rwlocktype_write);
16665 REQUIRE(source->refs > 0);
16666 source->refs++;
16667 INSIST(source->refs > 0);
16668 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
16669 *target = source;
16670}
16671
16672void
16673dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
16674 dns_zonemgr_t *zmgr;
16675 bool free_now = false;
16676
16677 REQUIRE(zmgrp != NULL);
16678 zmgr = *zmgrp;
16679 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16680
16681 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16682 zmgr->refs--;
16683 if (zmgr->refs == 0)
16684 free_now = true;
16685 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16686
16687 if (free_now)
16688 zonemgr_free(zmgr);
16689 *zmgrp = NULL;
16690}
16691
16692isc_result_t
16693dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
16694 dns_zone_t *p;
16695
16696 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16697
16698 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16699 for (p = ISC_LIST_HEAD(zmgr->zones);
16700 p != NULL;
16701 p = ISC_LIST_NEXT(p, link))
16702 {
16703 dns_zone_maintenance(p);
16704 }
16705 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16706
16707 /*
16708 * Recent configuration changes may have increased the
16709 * amount of available transfers quota. Make sure any
16710 * transfers currently blocked on quota get started if
16711 * possible.
16712 */
16713 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16714 zmgr_resume_xfrs(zmgr, true);
16715 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16716 return (ISC_R_SUCCESS);
16717}
16718
16719void
16720dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
16721
16722 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16723
16724 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16725 zmgr_resume_xfrs(zmgr, true);
16726 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16727}
16728
16729void
16730dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
16731 dns_zone_t *zone;
16732
16733 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16734
16735 isc_ratelimiter_shutdown(zmgr->notifyrl);
16736 isc_ratelimiter_shutdown(zmgr->refreshrl);
16737 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
16738 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
16739
16740 if (zmgr->task != NULL)
16741 isc_task_destroy(&zmgr->task);
16742 if (zmgr->zonetasks != NULL)
16743 isc_taskpool_destroy(&zmgr->zonetasks);
16744 if (zmgr->loadtasks != NULL)
16745 isc_taskpool_destroy(&zmgr->loadtasks);
16746 if (zmgr->mctxpool != NULL)
16747 isc_pool_destroy(&zmgr->mctxpool);
16748
16749 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16750 for (zone = ISC_LIST_HEAD(zmgr->zones);
16751 zone != NULL;
16752 zone = ISC_LIST_NEXT(zone, link))
16753 {
16754 LOCK_ZONE(zone);
16755 forward_cancel(zone);
16756 UNLOCK_ZONE(zone);
16757 }
16758 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16759}
16760
16761static isc_result_t
16762mctxinit(void **target, void *arg) {
16763 isc_result_t result;
16764 isc_mem_t *mctx = NULL;
16765
16766 UNUSED(arg);
16767
16768 REQUIRE(target != NULL && *target == NULL);
16769
16770 result = isc_mem_create(0, 0, &mctx);
16771 if (result != ISC_R_SUCCESS)
16772 return (result);
16773 isc_mem_setname(mctx, "zonemgr-pool", NULL);
16774
16775 *target = mctx;
16776 return (ISC_R_SUCCESS);
16777}
16778
16779static void
16780mctxfree(void **target) {
16781 isc_mem_t *mctx = *(isc_mem_t **) target;
16782 isc_mem_detach(&mctx);
16783 *target = NULL;
16784}
16785
16786#define ZONES_PER_TASK 100
16787#define ZONES_PER_MCTX 1000
16788
16789isc_result_t
16790dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
16791 isc_result_t result;
16792 int ntasks = num_zones / ZONES_PER_TASK;
16793 int nmctx = num_zones / ZONES_PER_MCTX;
16794 isc_taskpool_t *pool = NULL;
16795 isc_pool_t *mctxpool = NULL;
16796
16797 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16798
16799 /*
16800 * For anything fewer than 1000 zones we use 10 tasks in
16801 * the task pools. More than that, and we'll scale at one
16802 * task per 100 zones. Similarly, for anything smaller than
16803 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
16804 */
16805 if (ntasks < 10)
16806 ntasks = 10;
16807 if (nmctx < 2)
16808 nmctx = 2;
16809
16810 /* Create or resize the zone task pools. */
16811 if (zmgr->zonetasks == NULL)
16812 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
16813 ntasks, 2, &pool);
16814 else
16815 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
16816
16817 if (result == ISC_R_SUCCESS)
16818 zmgr->zonetasks = pool;
16819
16820 pool = NULL;
16821 if (zmgr->loadtasks == NULL)
16822 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
16823 ntasks, 2, &pool);
16824 else
16825 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
16826
16827 if (result == ISC_R_SUCCESS)
16828 zmgr->loadtasks = pool;
16829
16830 /*
16831 * We always set all tasks in the zone-load task pool to
16832 * privileged. This prevents other tasks in the system from
16833 * running while the server task manager is in privileged
16834 * mode.
16835 *
16836 * NOTE: If we start using task privileges for any other
16837 * part of the system than zone tasks, then this will need to be
16838 * revisted. In that case we'd want to turn on privileges for
16839 * zone tasks only when we were loading, and turn them off the
16840 * rest of the time. For now, however, it's okay to just
16841 * set it and forget it.
16842 */
16843 isc_taskpool_setprivilege(zmgr->loadtasks, true);
16844
16845 /* Create or resize the zone memory context pool. */
16846 if (zmgr->mctxpool == NULL)
16847 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
16848 mctxinit, NULL, &mctxpool);
16849 else
16850 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
16851
16852 if (result == ISC_R_SUCCESS)
16853 zmgr->mctxpool = mctxpool;
16854
16855 return (result);
16856}
16857
16858static void
16859zonemgr_free(dns_zonemgr_t *zmgr) {
16860 isc_mem_t *mctx;
16861
16862 INSIST(zmgr->refs == 0);
16863 INSIST(ISC_LIST_EMPTY(zmgr->zones));
16864
16865 zmgr->magic = 0;
16866
16867 isc_mutex_destroy(&zmgr->iolock);
16868 isc_ratelimiter_detach(&zmgr->notifyrl);
16869 isc_ratelimiter_detach(&zmgr->refreshrl);
16870 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
16871 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
16872
16873 isc_rwlock_destroy(&zmgr->urlock);
16874 isc_rwlock_destroy(&zmgr->rwlock);
16875 mctx = zmgr->mctx;
16876 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
16877 isc_mem_detach(&mctx);
16878}
16879
16880void
16881dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
16882 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16883
16884 zmgr->transfersin = value;
16885}
16886
16887uint32_t
16888dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
16889 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16890
16891 return (zmgr->transfersin);
16892}
16893
16894void
16895dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
16896 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16897
16898 zmgr->transfersperns = value;
16899}
16900
16901uint32_t
16902dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
16903 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16904
16905 return (zmgr->transfersperns);
16906}
16907
16908/*
16909 * Try to start a new incoming zone transfer to fill a quota
16910 * slot that was just vacated.
16911 *
16912 * Requires:
16913 * The zone manager is locked by the caller.
16914 */
16915static void
16916zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
16917 dns_zone_t *zone;
16918 dns_zone_t *next;
16919
16920 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
16921 zone != NULL;
16922 zone = next)
16923 {
16924 isc_result_t result;
16925 next = ISC_LIST_NEXT(zone, statelink);
16926 result = zmgr_start_xfrin_ifquota(zmgr, zone);
16927 if (result == ISC_R_SUCCESS) {
16928 if (multi)
16929 continue;
16930 /*
16931 * We successfully filled the slot. We're done.
16932 */
16933 break;
16934 } else if (result == ISC_R_QUOTA) {
16935 /*
16936 * Not enough quota. This is probably the per-server
16937 * quota, because we usually get called when a unit of
16938 * global quota has just been freed. Try the next
16939 * zone, it may succeed if it uses another master.
16940 */
16941 continue;
16942 } else {
16943 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16944 "starting zone transfer: %s",
16945 isc_result_totext(result));
16946 break;
16947 }
16948 }
16949}
16950
16951/*
16952 * Try to start an incoming zone transfer for 'zone', quota permitting.
16953 *
16954 * Requires:
16955 * The zone manager is locked by the caller.
16956 *
16957 * Returns:
16958 * ISC_R_SUCCESS There was enough quota and we attempted to
16959 * start a transfer. zone_xfrdone() has been or will
16960 * be called.
16961 * ISC_R_QUOTA Not enough quota.
16962 * Others Failure.
16963 */
16964static isc_result_t
16965zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16966 dns_peer_t *peer = NULL;
16967 isc_netaddr_t masterip;
16968 uint32_t nxfrsin, nxfrsperns;
16969 dns_zone_t *x;
16970 uint32_t maxtransfersin, maxtransfersperns;
16971 isc_event_t *e;
16972
16973 /*
16974 * If we are exiting just pretend we got quota so the zone will
16975 * be cleaned up in the zone's task context.
16976 */
16977 LOCK_ZONE(zone);
16978 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
16979 UNLOCK_ZONE(zone);
16980 goto gotquota;
16981 }
16982
16983 /*
16984 * Find any configured information about the server we'd
16985 * like to transfer this zone from.
16986 */
16987 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
16988 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
16989 UNLOCK_ZONE(zone);
16990
16991 /*
16992 * Determine the total maximum number of simultaneous
16993 * transfers allowed, and the maximum for this specific
16994 * master.
16995 */
16996 maxtransfersin = zmgr->transfersin;
16997 maxtransfersperns = zmgr->transfersperns;
16998 if (peer != NULL)
16999 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
17000
17001 /*
17002 * Count the total number of transfers that are in progress,
17003 * and the number of transfers in progress from this master.
17004 * We linearly scan a list of all transfers; if this turns
17005 * out to be too slow, we could hash on the master address.
17006 */
17007 nxfrsin = nxfrsperns = 0;
17008 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
17009 x != NULL;
17010 x = ISC_LIST_NEXT(x, statelink))
17011 {
17012 isc_netaddr_t xip;
17013
17014 LOCK_ZONE(x);
17015 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
17016 UNLOCK_ZONE(x);
17017
17018 nxfrsin++;
17019 if (isc_netaddr_equal(&xip, &masterip))
17020 nxfrsperns++;
17021 }
17022
17023 /* Enforce quota. */
17024 if (nxfrsin >= maxtransfersin)
17025 return (ISC_R_QUOTA);
17026
17027 if (nxfrsperns >= maxtransfersperns)
17028 return (ISC_R_QUOTA);
17029
17030 gotquota:
17031 /*
17032 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
17033 * list and send it an event to let it start the actual transfer in the
17034 * context of its own task.
17035 */
17036 e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
17037 got_transfer_quota, zone, sizeof(isc_event_t));
17038 if (e == NULL)
17039 return (ISC_R_NOMEMORY);
17040
17041 LOCK_ZONE(zone);
17042 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
17043 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
17044 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
17045 zone->statelist = &zmgr->xfrin_in_progress;
17046 isc_task_send(zone->task, &e);
17047 dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
17048 UNLOCK_ZONE(zone);
17049
17050 return (ISC_R_SUCCESS);
17051}
17052
17053void
17054dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
17055
17056 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17057 REQUIRE(iolimit > 0);
17058
17059 zmgr->iolimit = iolimit;
17060}
17061
17062uint32_t
17063dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
17064
17065 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17066
17067 return (zmgr->iolimit);
17068}
17069
17070/*
17071 * Get permission to request a file handle from the OS.
17072 * An event will be sent to action when one is available.
17073 * There are two queues available (high and low), the high
17074 * queue will be serviced before the low one.
17075 *
17076 * zonemgr_putio() must be called after the event is delivered to
17077 * 'action'.
17078 */
17079
17080static isc_result_t
17081zonemgr_getio(dns_zonemgr_t *zmgr, bool high,
17082 isc_task_t *task, isc_taskaction_t action, void *arg,
17083 dns_io_t **iop)
17084{
17085 dns_io_t *io;
17086 bool queue;
17087
17088 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17089 REQUIRE(iop != NULL && *iop == NULL);
17090
17091 io = isc_mem_get(zmgr->mctx, sizeof(*io));
17092 if (io == NULL)
17093 return (ISC_R_NOMEMORY);
17094
17095 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
17096 action, arg, sizeof(*io->event));
17097 if (io->event == NULL) {
17098 isc_mem_put(zmgr->mctx, io, sizeof(*io));
17099 return (ISC_R_NOMEMORY);
17100 }
17101
17102 io->zmgr = zmgr;
17103 io->high = high;
17104 io->task = NULL;
17105 isc_task_attach(task, &io->task);
17106 ISC_LINK_INIT(io, link);
17107 io->magic = IO_MAGIC;
17108
17109 LOCK(&zmgr->iolock);
17110 zmgr->ioactive++;
17111 queue = (zmgr->ioactive > zmgr->iolimit);
17112 if (queue) {
17113 if (io->high)
17114 ISC_LIST_APPEND(zmgr->high, io, link);
17115 else
17116 ISC_LIST_APPEND(zmgr->low, io, link);
17117 }
17118 UNLOCK(&zmgr->iolock);
17119 *iop = io;
17120
17121 if (!queue)
17122 isc_task_send(io->task, &io->event);
17123 return (ISC_R_SUCCESS);
17124}
17125
17126static void
17127zonemgr_putio(dns_io_t **iop) {
17128 dns_io_t *io;
17129 dns_io_t *next;
17130 dns_zonemgr_t *zmgr;
17131
17132 REQUIRE(iop != NULL);
17133 io = *iop;
17134 REQUIRE(DNS_IO_VALID(io));
17135
17136 *iop = NULL;
17137
17138 INSIST(!ISC_LINK_LINKED(io, link));
17139 INSIST(io->event == NULL);
17140
17141 zmgr = io->zmgr;
17142 isc_task_detach(&io->task);
17143 io->magic = 0;
17144 isc_mem_put(zmgr->mctx, io, sizeof(*io));
17145
17146 LOCK(&zmgr->iolock);
17147 INSIST(zmgr->ioactive > 0);
17148 zmgr->ioactive--;
17149 next = HEAD(zmgr->high);
17150 if (next == NULL)
17151 next = HEAD(zmgr->low);
17152 if (next != NULL) {
17153 if (next->high)
17154 ISC_LIST_UNLINK(zmgr->high, next, link);
17155 else
17156 ISC_LIST_UNLINK(zmgr->low, next, link);
17157 INSIST(next->event != NULL);
17158 }
17159 UNLOCK(&zmgr->iolock);
17160 if (next != NULL)
17161 isc_task_send(next->task, &next->event);
17162}
17163
17164static void
17165zonemgr_cancelio(dns_io_t *io) {
17166 bool send_event = false;
17167
17168 REQUIRE(DNS_IO_VALID(io));
17169
17170 /*
17171 * If we are queued to be run then dequeue.
17172 */
17173 LOCK(&io->zmgr->iolock);
17174 if (ISC_LINK_LINKED(io, link)) {
17175 if (io->high)
17176 ISC_LIST_UNLINK(io->zmgr->high, io, link);
17177 else
17178 ISC_LIST_UNLINK(io->zmgr->low, io, link);
17179
17180 send_event = true;
17181 INSIST(io->event != NULL);
17182 }
17183 UNLOCK(&io->zmgr->iolock);
17184 if (send_event) {
17185 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
17186 isc_task_send(io->task, &io->event);
17187 }
17188}
17189
17190static void
17191zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
17192 char *buf;
17193 int buflen;
17194 isc_result_t result;
17195
17196 buflen = strlen(path) + strlen(templat) + 2;
17197
17198 buf = isc_mem_get(zone->mctx, buflen);
17199 if (buf == NULL)
17200 return;
17201
17202 result = isc_file_template(path, templat, buf, buflen);
17203 if (result != ISC_R_SUCCESS)
17204 goto cleanup;
17205
17206 result = isc_file_renameunique(path, buf);
17207 if (result != ISC_R_SUCCESS)
17208 goto cleanup;
17209
17210 dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
17211 "renaming file to '%s' for failure analysis and "
17212 "retransferring.", path, buf);
17213
17214 cleanup:
17215 isc_mem_put(zone->mctx, buf, buflen);
17216}
17217
17218static void
17219setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
17220 isc_interval_t interval;
17221 uint32_t s, ns;
17222 uint32_t pertic;
17223 isc_result_t result;
17224
17225 if (value == 0)
17226 value = 1;
17227
17228 if (value == 1) {
17229 s = 1;
17230 ns = 0;
17231 pertic = 1;
17232 } else if (value <= 10) {
17233 s = 0;
17234 ns = 1000000000 / value;
17235 pertic = 1;
17236 } else {
17237 s = 0;
17238 ns = (1000000000 / value) * 10;
17239 pertic = 10;
17240 }
17241
17242 isc_interval_set(&interval, s, ns);
17243
17244 result = isc_ratelimiter_setinterval(rl, &interval);
17245 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17246 isc_ratelimiter_setpertic(rl, pertic);
17247
17248 *rate = value;
17249}
17250
17251void
17252dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
17253
17254 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17255
17256 setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
17257}
17258
17259void
17260dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
17261
17262 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17263
17264 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
17265}
17266
17267void
17268dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
17269
17270 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17271
17272 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
17273 /* XXXMPA seperate out once we have the code to support this. */
17274 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
17275}
17276
17277unsigned int
17278dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
17279 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17280
17281 return (zmgr->notifyrate);
17282}
17283
17284unsigned int
17285dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
17286 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17287
17288 return (zmgr->startupnotifyrate);
17289}
17290
17291unsigned int
17292dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
17293 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17294
17295 return (zmgr->serialqueryrate);
17296}
17297
17298bool
17299dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
17300 isc_sockaddr_t *local, isc_time_t *now)
17301{
17302 unsigned int i;
17303 isc_rwlocktype_t locktype;
17304 isc_result_t result;
17305 uint32_t seconds = isc_time_seconds(now);
17306 uint32_t count = 0;
17307
17308 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17309
17310 locktype = isc_rwlocktype_read;
17311 RWLOCK(&zmgr->urlock, locktype);
17312 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17313 if (zmgr->unreachable[i].expire >= seconds &&
17314 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17315 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
17316 result = isc_rwlock_tryupgrade(&zmgr->urlock);
17317 if (result == ISC_R_SUCCESS) {
17318 locktype = isc_rwlocktype_write;
17319 zmgr->unreachable[i].last = seconds;
17320 count = zmgr->unreachable[i].count;
17321 }
17322 break;
17323 }
17324 }
17325 RWUNLOCK(&zmgr->urlock, locktype);
17326 return (i < UNREACH_CHACHE_SIZE && count > 1U);
17327}
17328
17329void
17330dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
17331 isc_sockaddr_t *local)
17332{
17333 unsigned int i;
17334 isc_rwlocktype_t locktype;
17335 isc_result_t result;
17336
17337 char master[ISC_SOCKADDR_FORMATSIZE];
17338 char source[ISC_SOCKADDR_FORMATSIZE];
17339
17340 isc_sockaddr_format(remote, master, sizeof(master));
17341 isc_sockaddr_format(local, source, sizeof(source));
17342
17343 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17344
17345 locktype = isc_rwlocktype_read;
17346 RWLOCK(&zmgr->urlock, locktype);
17347 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17348 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17349 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
17350 if (zmgr->unreachable[i].expire == 0)
17351 break;
17352 result = isc_rwlock_tryupgrade(&zmgr->urlock);
17353 if (result == ISC_R_SUCCESS) {
17354 locktype = isc_rwlocktype_write;
17355 zmgr->unreachable[i].expire = 0;
17356 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17357 DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
17358 "master %s (source %s) deleted "
17359 "from unreachable cache",
17360 master, source);
17361 }
17362 break;
17363 }
17364 }
17365 RWUNLOCK(&zmgr->urlock, locktype);
17366}
17367
17368void
17369dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
17370 isc_sockaddr_t *local, isc_time_t *now)
17371{
17372 uint32_t seconds = isc_time_seconds(now);
17373 uint32_t last = seconds;
17374 unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
17375
17376 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17377
17378 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
17379 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17380 /* Existing entry? */
17381 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17382 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
17383 break;
17384 /* Empty slot? */
17385 if (zmgr->unreachable[i].expire < seconds)
17386 slot = i;
17387 /* Least recently used slot? */
17388 if (zmgr->unreachable[i].last < last) {
17389 last = zmgr->unreachable[i].last;
17390 oldest = i;
17391 }
17392 }
17393 if (i < UNREACH_CHACHE_SIZE) {
17394 /*
17395 * Found a existing entry. Update the expire timer and
17396 * last usage timestamps.
17397 */
17398 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
17399 zmgr->unreachable[i].last = seconds;
17400 if (zmgr->unreachable[i].expire < seconds)
17401 zmgr->unreachable[i].count = 1;
17402 else
17403 zmgr->unreachable[i].count++;
17404 } else if (slot != UNREACH_CHACHE_SIZE) {
17405 /*
17406 * Found a empty slot. Add a new entry to the cache.
17407 */
17408 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
17409 zmgr->unreachable[slot].last = seconds;
17410 zmgr->unreachable[slot].remote = *remote;
17411 zmgr->unreachable[slot].local = *local;
17412 zmgr->unreachable[slot].count = 1;
17413 } else {
17414 /*
17415 * Replace the least recently used entry in the cache.
17416 */
17417 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
17418 zmgr->unreachable[oldest].last = seconds;
17419 zmgr->unreachable[oldest].remote = *remote;
17420 zmgr->unreachable[oldest].local = *local;
17421 zmgr->unreachable[oldest].count = 1;
17422 }
17423 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
17424}
17425
17426void
17427dns_zone_forcereload(dns_zone_t *zone) {
17428 REQUIRE(DNS_ZONE_VALID(zone));
17429
17430 if (zone->type == dns_zone_master ||
17431 (zone->type == dns_zone_redirect && zone->masters == NULL))
17432 return;
17433
17434 LOCK_ZONE(zone);
17435 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17436 UNLOCK_ZONE(zone);
17437 dns_zone_refresh(zone);
17438}
17439
17440bool
17441dns_zone_isforced(dns_zone_t *zone) {
17442 REQUIRE(DNS_ZONE_VALID(zone));
17443
17444 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
17445}
17446
17447isc_result_t
17448dns_zone_setstatistics(dns_zone_t *zone, bool on) {
17449 /*
17450 * This function is obsoleted.
17451 */
17452 UNUSED(zone);
17453 UNUSED(on);
17454 return (ISC_R_NOTIMPLEMENTED);
17455}
17456
17457uint64_t *
17458dns_zone_getstatscounters(dns_zone_t *zone) {
17459 /*
17460 * This function is obsoleted.
17461 */
17462 UNUSED(zone);
17463 return (NULL);
17464}
17465
17466void
17467dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
17468 REQUIRE(DNS_ZONE_VALID(zone));
17469 REQUIRE(zone->stats == NULL);
17470
17471 LOCK_ZONE(zone);
17472 zone->stats = NULL;
17473 isc_stats_attach(stats, &zone->stats);
17474 UNLOCK_ZONE(zone);
17475}
17476
17477void
17478dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
17479
17480 REQUIRE(DNS_ZONE_VALID(zone));
17481
17482 LOCK_ZONE(zone);
17483 if (zone->requeststats_on && stats == NULL)
17484 zone->requeststats_on = false;
17485 else if (!zone->requeststats_on && stats != NULL) {
17486 if (zone->requeststats == NULL) {
17487 isc_stats_attach(stats, &zone->requeststats);
17488 zone->requeststats_on = true;
17489 }
17490 }
17491 UNLOCK_ZONE(zone);
17492}
17493
17494void
17495dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
17496
17497 REQUIRE(DNS_ZONE_VALID(zone));
17498
17499 LOCK_ZONE(zone);
17500 if (zone->requeststats_on && stats != NULL) {
17501 if (zone->rcvquerystats == NULL) {
17502 dns_stats_attach(stats, &zone->rcvquerystats);
17503 zone->requeststats_on = true;
17504 }
17505 }
17506 UNLOCK_ZONE(zone);
17507}
17508
17509isc_stats_t *
17510dns_zone_getrequeststats(dns_zone_t *zone) {
17511 /*
17512 * We don't lock zone for efficiency reason. This is not catastrophic
17513 * because requeststats must always be valid when requeststats_on is
17514 * true.
17515 * Some counters may be incremented while requeststats_on is becoming
17516 * false, or some cannot be incremented just after the statistics are
17517 * installed, but it shouldn't matter much in practice.
17518 */
17519 if (zone->requeststats_on)
17520 return (zone->requeststats);
17521 else
17522 return (NULL);
17523}
17524
17525/*
17526 * Return the received query stats bucket
17527 * see note from dns_zone_getrequeststats()
17528 */
17529dns_stats_t *
17530dns_zone_getrcvquerystats(dns_zone_t *zone) {
17531 if (zone->requeststats_on)
17532 return (zone->rcvquerystats);
17533 else
17534 return (NULL);
17535}
17536
17537void
17538dns_zone_dialup(dns_zone_t *zone) {
17539
17540 REQUIRE(DNS_ZONE_VALID(zone));
17541
17542 zone_debuglog(zone, "dns_zone_dialup", 3,
17543 "notify = %d, refresh = %d",
17544 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
17545 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
17546
17547 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
17548 dns_zone_notify(zone);
17549 if (zone->type != dns_zone_master && zone->masters != NULL &&
17550 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
17551 dns_zone_refresh(zone);
17552}
17553
17554void
17555dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
17556 REQUIRE(DNS_ZONE_VALID(zone));
17557
17558 LOCK_ZONE(zone);
17559 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
17560 DNS_ZONEFLG_DIALREFRESH |
17561 DNS_ZONEFLG_NOREFRESH);
17562 switch (dialup) {
17563 case dns_dialuptype_no:
17564 break;
17565 case dns_dialuptype_yes:
17566 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
17567 DNS_ZONEFLG_DIALREFRESH |
17568 DNS_ZONEFLG_NOREFRESH));
17569 break;
17570 case dns_dialuptype_notify:
17571 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
17572 break;
17573 case dns_dialuptype_notifypassive:
17574 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
17575 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17576 break;
17577 case dns_dialuptype_refresh:
17578 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
17579 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17580 break;
17581 case dns_dialuptype_passive:
17582 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17583 break;
17584 default:
17585 INSIST(0);
17586 ISC_UNREACHABLE();
17587 }
17588 UNLOCK_ZONE(zone);
17589}
17590
17591isc_result_t
17592dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
17593 isc_result_t result = ISC_R_SUCCESS;
17594
17595 REQUIRE(DNS_ZONE_VALID(zone));
17596
17597 LOCK_ZONE(zone);
17598 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
17599 UNLOCK_ZONE(zone);
17600
17601 return (result);
17602}
17603
17604const char *
17605dns_zone_getkeydirectory(dns_zone_t *zone) {
17606 REQUIRE(DNS_ZONE_VALID(zone));
17607
17608 return (zone->keydirectory);
17609}
17610
17611unsigned int
17612dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
17613 dns_zone_t *zone;
17614 unsigned int count = 0;
17615
17616 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17617
17618 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
17619 switch (state) {
17620 case DNS_ZONESTATE_XFERRUNNING:
17621 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
17622 zone != NULL;
17623 zone = ISC_LIST_NEXT(zone, statelink))
17624 count++;
17625 break;
17626 case DNS_ZONESTATE_XFERDEFERRED:
17627 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
17628 zone != NULL;
17629 zone = ISC_LIST_NEXT(zone, statelink))
17630 count++;
17631 break;
17632 case DNS_ZONESTATE_SOAQUERY:
17633 for (zone = ISC_LIST_HEAD(zmgr->zones);
17634 zone != NULL;
17635 zone = ISC_LIST_NEXT(zone, link))
17636 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
17637 count++;
17638 break;
17639 case DNS_ZONESTATE_ANY:
17640 for (zone = ISC_LIST_HEAD(zmgr->zones);
17641 zone != NULL;
17642 zone = ISC_LIST_NEXT(zone, link)) {
17643 dns_view_t *view = zone->view;
17644 if (view != NULL && strcmp(view->name, "_bind") == 0)
17645 continue;
17646 count++;
17647 }
17648 break;
17649 case DNS_ZONESTATE_AUTOMATIC:
17650 for (zone = ISC_LIST_HEAD(zmgr->zones);
17651 zone != NULL;
17652 zone = ISC_LIST_NEXT(zone, link)) {
17653 dns_view_t *view = zone->view;
17654 if (view != NULL && strcmp(view->name, "_bind") == 0)
17655 continue;
17656 if (zone->automatic)
17657 count++;
17658 }
17659 break;
17660 default:
17661 INSIST(0);
17662 ISC_UNREACHABLE();
17663 }
17664
17665 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
17666
17667 return (count);
17668}
17669
17670isc_result_t
17671dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
17672 dns_rdata_t *rdata)
17673{
17674 bool ok = true;
17675 bool fail = false;
17676 char namebuf[DNS_NAME_FORMATSIZE];
17677 char namebuf2[DNS_NAME_FORMATSIZE];
17678 char typebuf[DNS_RDATATYPE_FORMATSIZE];
17679 int level = ISC_LOG_WARNING;
17680 dns_name_t bad;
17681
17682 REQUIRE(DNS_ZONE_VALID(zone));
17683
17684 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
17685 rdata->type != dns_rdatatype_nsec3)
17686 return (ISC_R_SUCCESS);
17687
17688 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
17689 rdata->type == dns_rdatatype_nsec3) {
17690 level = ISC_LOG_ERROR;
17691 fail = true;
17692 }
17693
17694 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
17695 if (!ok) {
17696 dns_name_format(name, namebuf, sizeof(namebuf));
17697 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
17698 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
17699 dns_result_totext(DNS_R_BADOWNERNAME));
17700 if (fail)
17701 return (DNS_R_BADOWNERNAME);
17702 }
17703
17704 dns_name_init(&bad, NULL);
17705 ok = dns_rdata_checknames(rdata, name, &bad);
17706 if (!ok) {
17707 dns_name_format(name, namebuf, sizeof(namebuf));
17708 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
17709 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
17710 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
17711 namebuf2, dns_result_totext(DNS_R_BADNAME));
17712 if (fail)
17713 return (DNS_R_BADNAME);
17714 }
17715
17716 return (ISC_R_SUCCESS);
17717}
17718
17719void
17720dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
17721 REQUIRE(DNS_ZONE_VALID(zone));
17722 zone->checkmx = checkmx;
17723}
17724
17725void
17726dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
17727 REQUIRE(DNS_ZONE_VALID(zone));
17728 zone->checksrv = checksrv;
17729}
17730
17731void
17732dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
17733 REQUIRE(DNS_ZONE_VALID(zone));
17734 zone->checkns = checkns;
17735}
17736
17737void
17738dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
17739 REQUIRE(DNS_ZONE_VALID(zone));
17740
17741 LOCK_ZONE(zone);
17742 zone->isself = isself;
17743 zone->isselfarg = arg;
17744 UNLOCK_ZONE(zone);
17745}
17746
17747void
17748dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
17749 REQUIRE(DNS_ZONE_VALID(zone));
17750
17751 LOCK_ZONE(zone);
17752 zone->notifydelay = delay;
17753 UNLOCK_ZONE(zone);
17754}
17755
17756uint32_t
17757dns_zone_getnotifydelay(dns_zone_t *zone) {
17758 REQUIRE(DNS_ZONE_VALID(zone));
17759
17760 return (zone->notifydelay);
17761}
17762
17763isc_result_t
17764dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
17765 uint16_t keyid, bool deleteit)
17766{
17767 isc_result_t result;
17768 REQUIRE(DNS_ZONE_VALID(zone));
17769
17770 dnssec_log(zone, ISC_LOG_NOTICE,
17771 "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
17772 algorithm, keyid);
17773 LOCK_ZONE(zone);
17774 result = zone_signwithkey(zone, algorithm, keyid, deleteit);
17775 UNLOCK_ZONE(zone);
17776
17777 return (result);
17778}
17779
17780/*
17781 * Called when a dynamic update for an NSEC3PARAM record is received.
17782 *
17783 * If set, transform the NSEC3 salt into human-readable form so that it can be
17784 * logged. Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
17785 */
17786isc_result_t
17787dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
17788 isc_result_t result;
17789 char salt[255*2+1];
17790
17791 REQUIRE(DNS_ZONE_VALID(zone));
17792
17793 result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
17794 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17795 dnssec_log(zone, ISC_LOG_NOTICE,
17796 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
17797 nsec3param->hash, nsec3param->iterations, salt);
17798 LOCK_ZONE(zone);
17799 result = zone_addnsec3chain(zone, nsec3param);
17800 UNLOCK_ZONE(zone);
17801
17802 return (result);
17803}
17804
17805void
17806dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
17807 REQUIRE(DNS_ZONE_VALID(zone));
17808
17809 if (nodes == 0)
17810 nodes = 1;
17811 zone->nodes = nodes;
17812}
17813
17814void
17815dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
17816 REQUIRE(DNS_ZONE_VALID(zone));
17817
17818 /*
17819 * We treat signatures as a signed value so explicitly
17820 * limit its range here.
17821 */
17822 if (signatures > INT32_MAX)
17823 signatures = INT32_MAX;
17824 else if (signatures == 0)
17825 signatures = 1;
17826 zone->signatures = signatures;
17827}
17828
17829uint32_t
17830dns_zone_getsignatures(dns_zone_t *zone) {
17831 REQUIRE(DNS_ZONE_VALID(zone));
17832 return (zone->signatures);
17833}
17834
17835void
17836dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
17837 REQUIRE(DNS_ZONE_VALID(zone));
17838 zone->privatetype = type;
17839}
17840
17841dns_rdatatype_t
17842dns_zone_getprivatetype(dns_zone_t *zone) {
17843 REQUIRE(DNS_ZONE_VALID(zone));
17844 return (zone->privatetype);
17845}
17846
17847static isc_result_t
17848zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
17849 bool deleteit)
17850{
17851 dns_signing_t *signing;
17852 dns_signing_t *current;
17853 isc_result_t result = ISC_R_SUCCESS;
17854 isc_time_t now;
17855 dns_db_t *db = NULL;
17856
17857 signing = isc_mem_get(zone->mctx, sizeof *signing);
17858 if (signing == NULL)
17859 return (ISC_R_NOMEMORY);
17860
17861 signing->magic = 0;
17862 signing->db = NULL;
17863 signing->dbiterator = NULL;
17864 signing->algorithm = algorithm;
17865 signing->keyid = keyid;
17866 signing->deleteit = deleteit;
17867 signing->done = false;
17868
17869 TIME_NOW(&now);
17870
17871 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17872 if (zone->db != NULL)
17873 dns_db_attach(zone->db, &db);
17874 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17875
17876 if (db == NULL) {
17877 result = ISC_R_NOTFOUND;
17878 goto cleanup;
17879 }
17880
17881 dns_db_attach(db, &signing->db);
17882
17883 for (current = ISC_LIST_HEAD(zone->signing);
17884 current != NULL;
17885 current = ISC_LIST_NEXT(current, link)) {
17886 if (current->db == signing->db &&
17887 current->algorithm == signing->algorithm &&
17888 current->keyid == signing->keyid) {
17889 if (current->deleteit != signing->deleteit)
17890 current->done = true;
17891 else
17892 goto cleanup;
17893 }
17894 }
17895
17896 result = dns_db_createiterator(signing->db, 0,
17897 &signing->dbiterator);
17898
17899 if (result == ISC_R_SUCCESS)
17900 result = dns_dbiterator_first(signing->dbiterator);
17901 if (result == ISC_R_SUCCESS) {
17902 dns_dbiterator_pause(signing->dbiterator);
17903 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
17904 signing = NULL;
17905 if (isc_time_isepoch(&zone->signingtime)) {
17906 zone->signingtime = now;
17907 if (zone->task != NULL)
17908 zone_settimer(zone, &now);
17909 }
17910 }
17911
17912 cleanup:
17913 if (signing != NULL) {
17914 if (signing->db != NULL)
17915 dns_db_detach(&signing->db);
17916 if (signing->dbiterator != NULL)
17917 dns_dbiterator_destroy(&signing->dbiterator);
17918 isc_mem_put(zone->mctx, signing, sizeof *signing);
17919 }
17920 if (db != NULL)
17921 dns_db_detach(&db);
17922 return (result);
17923}
17924
17925static void
17926clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
17927 dns_dnsseckey_t *key;
17928 while (!ISC_LIST_EMPTY(*list)) {
17929 key = ISC_LIST_HEAD(*list);
17930 ISC_LIST_UNLINK(*list, key, link);
17931 dns_dnsseckey_destroy(mctx, &key);
17932 }
17933}
17934
17935/* Called once; *timep should be set to the current time. */
17936static isc_result_t
17937next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
17938 isc_result_t result;
17939 isc_stdtime_t now, then = 0, event;
17940 int i;
17941
17942 now = *timep;
17943
17944 for (i = 0; i <= DST_MAX_TIMES; i++) {
17945 result = dst_key_gettime(key, i, &event);
17946 if (result == ISC_R_SUCCESS && event > now &&
17947 (then == 0 || event < then))
17948 then = event;
17949 }
17950
17951 if (then != 0) {
17952 *timep = then;
17953 return (ISC_R_SUCCESS);
17954 }
17955
17956 return (ISC_R_NOTFOUND);
17957}
17958
17959static isc_result_t
17960rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
17961 const dns_rdata_t *rdata, bool *flag)
17962{
17963 dns_rdataset_t rdataset;
17964 dns_dbnode_t *node = NULL;
17965 isc_result_t result;
17966
17967 dns_rdataset_init(&rdataset);
17968 if (rdata->type == dns_rdatatype_nsec3)
17969 CHECK(dns_db_findnsec3node(db, name, false, &node));
17970 else
17971 CHECK(dns_db_findnode(db, name, false, &node));
17972 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
17973 (isc_stdtime_t) 0, &rdataset, NULL);
17974 if (result == ISC_R_NOTFOUND) {
17975 *flag = false;
17976 result = ISC_R_SUCCESS;
17977 goto failure;
17978 }
17979
17980 for (result = dns_rdataset_first(&rdataset);
17981 result == ISC_R_SUCCESS;
17982 result = dns_rdataset_next(&rdataset)) {
17983 dns_rdata_t myrdata = DNS_RDATA_INIT;
17984 dns_rdataset_current(&rdataset, &myrdata);
17985 if (!dns_rdata_compare(&myrdata, rdata))
17986 break;
17987 }
17988 dns_rdataset_disassociate(&rdataset);
17989 if (result == ISC_R_SUCCESS) {
17990 *flag = true;
17991 } else if (result == ISC_R_NOMORE) {
17992 *flag = false;
17993 result = ISC_R_SUCCESS;
17994 }
17995
17996 failure:
17997 if (node != NULL)
17998 dns_db_detachnode(db, &node);
17999 return (result);
18000}
18001
18002/*
18003 * Add records to signal the state of signing or of key removal.
18004 */
18005static isc_result_t
18006add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
18007 dns_dbversion_t *ver, dns_diff_t *diff,
18008 bool sign_all)
18009{
18010 dns_difftuple_t *tuple, *newtuple = NULL;
18011 dns_rdata_dnskey_t dnskey;
18012 dns_rdata_t rdata = DNS_RDATA_INIT;
18013 bool flag;
18014 isc_region_t r;
18015 isc_result_t result = ISC_R_SUCCESS;
18016 uint16_t keyid;
18017 unsigned char buf[5];
18018 dns_name_t *name = dns_db_origin(db);
18019
18020 for (tuple = ISC_LIST_HEAD(diff->tuples);
18021 tuple != NULL;
18022 tuple = ISC_LIST_NEXT(tuple, link)) {
18023 if (tuple->rdata.type != dns_rdatatype_dnskey)
18024 continue;
18025
18026 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
18027 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18028 if ((dnskey.flags &
18029 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
18030 != DNS_KEYOWNER_ZONE)
18031 continue;
18032
18033 dns_rdata_toregion(&tuple->rdata, &r);
18034
18035 keyid = dst_region_computeid(&r);
18036
18037 buf[0] = dnskey.algorithm;
18038 buf[1] = (keyid & 0xff00) >> 8;
18039 buf[2] = (keyid & 0xff);
18040 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
18041 buf[4] = 0;
18042 rdata.data = buf;
18043 rdata.length = sizeof(buf);
18044 rdata.type = privatetype;
18045 rdata.rdclass = tuple->rdata.rdclass;
18046
18047 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
18048 CHECK(rr_exists(db, ver, name, &rdata, &flag));
18049 if (flag)
18050 continue;
18051 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
18052 name, 0, &rdata, &newtuple));
18053 CHECK(do_one_tuple(&newtuple, db, ver, diff));
18054 INSIST(newtuple == NULL);
18055 }
18056
18057 /*
18058 * Remove any record which says this operation has already
18059 * completed.
18060 */
18061 buf[4] = 1;
18062 CHECK(rr_exists(db, ver, name, &rdata, &flag));
18063 if (flag) {
18064 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
18065 name, 0, &rdata, &newtuple));
18066 CHECK(do_one_tuple(&newtuple, db, ver, diff));
18067 INSIST(newtuple == NULL);
18068 }
18069 }
18070 failure:
18071 return (result);
18072}
18073
18074static isc_result_t
18075sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18076 isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff)
18077{
18078 isc_result_t result;
18079 isc_stdtime_t inception, soaexpire, keyexpire;
18080 bool check_ksk, keyset_kskonly;
18081 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
18082 unsigned int nkeys = 0, i;
18083 dns_difftuple_t *tuple;
18084
18085 result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
18086 DNS_MAXZONEKEYS, zone_keys, &nkeys);
18087 if (result != ISC_R_SUCCESS) {
18088 dnssec_log(zone, ISC_LOG_ERROR,
18089 "sign_apex:dns__zone_findkeys -> %s",
18090 dns_result_totext(result));
18091 return (result);
18092 }
18093
18094 inception = now - 3600; /* Allow for clock skew. */
18095 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
18096
18097 keyexpire = dns_zone_getkeyvalidityinterval(zone);
18098 if (keyexpire == 0) {
18099 keyexpire = soaexpire - 1;
18100 } else {
18101 keyexpire += now;
18102 }
18103
18104 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
18105 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
18106
18107 /*
18108 * See if dns__zone_updatesigs() will update DNSKEY signature and if
18109 * not cause them to sign so that newly activated keys are used.
18110 */
18111 for (tuple = ISC_LIST_HEAD(diff->tuples);
18112 tuple != NULL;
18113 tuple = ISC_LIST_NEXT(tuple, link))
18114 {
18115 if (tuple->rdata.type == dns_rdatatype_dnskey &&
18116 dns_name_equal(&tuple->name, &zone->origin))
18117 {
18118 break;
18119 }
18120 }
18121
18122 if (tuple == NULL) {
18123 result = del_sigs(zone, db, ver, &zone->origin,
18124 dns_rdatatype_dnskey, zonediff,
18125 zone_keys, nkeys, now, false);
18126 if (result != ISC_R_SUCCESS) {
18127 dnssec_log(zone, ISC_LOG_ERROR,
18128 "sign_apex:del_sigs -> %s",
18129 dns_result_totext(result));
18130 goto failure;
18131 }
18132 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
18133 zonediff->diff, zone_keys, nkeys, zone->mctx,
18134 inception, keyexpire, check_ksk,
18135 keyset_kskonly);
18136 if (result != ISC_R_SUCCESS) {
18137 dnssec_log(zone, ISC_LOG_ERROR,
18138 "sign_apex:add_sigs -> %s",
18139 dns_result_totext(result));
18140 goto failure;
18141 }
18142 }
18143
18144 result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
18145 inception, soaexpire, keyexpire, now,
18146 check_ksk, keyset_kskonly, zonediff);
18147
18148 if (result != ISC_R_SUCCESS) {
18149 dnssec_log(zone, ISC_LOG_ERROR,
18150 "sign_apex:dns__zone_updatesigs -> %s",
18151 dns_result_totext(result));
18152 goto failure;
18153 }
18154
18155 failure:
18156 for (i = 0; i < nkeys; i++) {
18157 dst_key_free(&zone_keys[i]);
18158 }
18159 return (result);
18160}
18161
18162/*
18163 * Prevent the zone entering a inconsistent state where
18164 * NSEC only DNSKEYs are present with NSEC3 chains.
18165 * See update.c:check_dnssec()
18166 */
18167static bool
18168dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18169 dns_diff_t *diff)
18170{
18171 isc_result_t result;
18172 dns_difftuple_t *tuple;
18173 bool nseconly = false, nsec3 = false;
18174 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
18175
18176 /* Scan the tuples for an NSEC-only DNSKEY */
18177 for (tuple = ISC_LIST_HEAD(diff->tuples);
18178 tuple != NULL;
18179 tuple = ISC_LIST_NEXT(tuple, link))
18180 {
18181 uint8_t alg;
18182 if (tuple->rdata.type != dns_rdatatype_dnskey ||
18183 tuple->op != DNS_DIFFOP_ADD)
18184 {
18185 continue;
18186 }
18187
18188 alg = tuple->rdata.data[3];
18189 if (alg == DST_ALG_RSASHA1) {
18190 nseconly = true;
18191 break;
18192 }
18193 }
18194
18195 /* Check existing DB for NSEC-only DNSKEY */
18196 if (!nseconly) {
18197 result = dns_nsec_nseconly(db, ver, &nseconly);
18198 if (result == ISC_R_NOTFOUND) {
18199 result = ISC_R_SUCCESS;
18200 }
18201 CHECK(result);
18202 }
18203
18204 /* Check existing DB for NSEC3 */
18205 if (!nsec3) {
18206 CHECK(dns_nsec3_activex(db, ver, false,
18207 privatetype, &nsec3));
18208 }
18209
18210 /* Refuse to allow NSEC3 with NSEC-only keys */
18211 if (nseconly && nsec3) {
18212 dnssec_log(zone, ISC_LOG_ERROR,
18213 "NSEC only DNSKEYs and NSEC3 chains not allowed");
18214 goto failure;
18215 }
18216
18217 return (true);
18218
18219 failure:
18220 return (false);
18221}
18222
18223static isc_result_t
18224clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18225 dns_diff_t *diff)
18226{
18227 isc_result_t result;
18228 dns_dbnode_t *node = NULL;
18229 dns_rdataset_t rdataset;
18230
18231 dns_rdataset_init(&rdataset);
18232 CHECK(dns_db_getoriginnode(db, &node));
18233
18234 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
18235 dns_rdatatype_none, 0, &rdataset, NULL);
18236 if (dns_rdataset_isassociated(&rdataset))
18237 dns_rdataset_disassociate(&rdataset);
18238 if (result != ISC_R_NOTFOUND)
18239 goto failure;
18240
18241 result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
18242
18243 failure:
18244 if (node != NULL)
18245 dns_db_detachnode(db, &node);
18246 return (result);
18247}
18248
18249/*
18250 * Given an RRSIG rdataset and an algorithm, determine whether there
18251 * are any signatures using that algorithm.
18252 */
18253static bool
18254signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
18255 dns_rdata_t rdata = DNS_RDATA_INIT;
18256 dns_rdata_rrsig_t rrsig;
18257 isc_result_t result;
18258
18259 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
18260 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
18261 return (false);
18262 }
18263
18264 for (result = dns_rdataset_first(rdataset);
18265 result == ISC_R_SUCCESS;
18266 result = dns_rdataset_next(rdataset))
18267 {
18268 dns_rdataset_current(rdataset, &rdata);
18269 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
18270 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18271 dns_rdata_reset(&rdata);
18272 if (rrsig.algorithm == alg)
18273 return (true);
18274 }
18275
18276 return (false);
18277}
18278
18279static isc_result_t
18280add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18281 dns_diff_t *diff)
18282{
18283 dns_name_t *origin;
18284 bool build_nsec3;
18285 isc_result_t result;
18286
18287 origin = dns_db_origin(db);
18288 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
18289 &build_nsec3));
18290 if (build_nsec3)
18291 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
18292 false, zone->privatetype, diff));
18293 CHECK(updatesecure(db, ver, origin, zone->minimum, true, diff));
18294
18295 failure:
18296 return (result);
18297}
18298
18299static void
18300dnssec_report(const char *format, ...) {
18301 va_list args;
18302 va_start(args, format);
18303 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
18304 ISC_LOG_INFO, format, args);
18305 va_end(args);
18306}
18307
18308static void
18309zone_rekey(dns_zone_t *zone) {
18310 isc_result_t result;
18311 dns_db_t *db = NULL;
18312 dns_dbnode_t *node = NULL;
18313 dns_dbversion_t *ver = NULL;
18314 dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
18315 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
18316 dns_dnsseckey_t *key = NULL;
18317 dns_diff_t diff, _sig_diff;
18318 dns__zonediff_t zonediff;
18319 bool commit = false, newactive = false;
18320 bool newalg = false;
18321 bool fullsign;
18322 dns_ttl_t ttl = 3600;
18323 const char *dir = NULL;
18324 isc_mem_t *mctx = NULL;
18325 isc_stdtime_t now;
18326 isc_time_t timenow;
18327 isc_interval_t ival;
18328 char timebuf[80];
18329
18330 REQUIRE(DNS_ZONE_VALID(zone));
18331
18332 ISC_LIST_INIT(dnskeys);
18333 ISC_LIST_INIT(keys);
18334 ISC_LIST_INIT(rmkeys);
18335 dns_rdataset_init(&soaset);
18336 dns_rdataset_init(&soasigs);
18337 dns_rdataset_init(&keyset);
18338 dns_rdataset_init(&keysigs);
18339 dns_rdataset_init(&cdsset);
18340 dns_rdataset_init(&cdnskeyset);
18341 dir = dns_zone_getkeydirectory(zone);
18342 mctx = zone->mctx;
18343 dns_diff_init(mctx, &diff);
18344 dns_diff_init(mctx, &_sig_diff);
18345 zonediff_init(&zonediff, &_sig_diff);
18346
18347 CHECK(dns_zone_getdb(zone, &db));
18348 CHECK(dns_db_newversion(db, &ver));
18349 CHECK(dns_db_getoriginnode(db, &node));
18350
18351 TIME_NOW(&timenow);
18352 now = isc_time_seconds(&timenow);
18353
18354 dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
18355
18356 /* Get the SOA record's TTL */
18357 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
18358 dns_rdatatype_none, 0, &soaset, &soasigs));
18359 ttl = soaset.ttl;
18360 dns_rdataset_disassociate(&soaset);
18361
18362 /* Get the DNSKEY rdataset */
18363 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
18364 dns_rdatatype_none, 0, &keyset, &keysigs);
18365 if (result == ISC_R_SUCCESS) {
18366 ttl = keyset.ttl;
18367 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
18368 mctx, &keyset,
18369 &keysigs, &soasigs,
18370 false, false,
18371 &dnskeys));
18372 } else if (result != ISC_R_NOTFOUND) {
18373 goto failure;
18374 }
18375
18376
18377 /* Get the CDS rdataset */
18378 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
18379 dns_rdatatype_none, 0, &cdsset, NULL);
18380 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset))
18381 dns_rdataset_disassociate(&cdsset);
18382
18383 /* Get the CDNSKEY rdataset */
18384 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
18385 dns_rdatatype_none, 0, &cdnskeyset, NULL);
18386 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset))
18387 {
18388 dns_rdataset_disassociate(&cdnskeyset);
18389 }
18390
18391 /*
18392 * True when called from "rndc sign". Indicates the zone should be
18393 * fully signed now.
18394 */
18395 fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
18396
18397 result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
18398 &keys);
18399 if (result == ISC_R_SUCCESS) {
18400 bool check_ksk;
18401 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
18402
18403 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
18404 &zone->origin, ttl, &diff,
18405 !check_ksk, mctx,
18406 dnssec_report);
18407 /*
18408 * Keys couldn't be updated for some reason;
18409 * try again later.
18410 */
18411 if (result != ISC_R_SUCCESS) {
18412 dnssec_log(zone, ISC_LOG_ERROR,
18413 "zone_rekey:couldn't update zone keys: %s",
18414 isc_result_totext(result));
18415 goto failure;
18416 }
18417
18418 /*
18419 * Update CDS / CDNSKEY records.
18420 */
18421 result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
18422 &cdnskeyset, now, ttl,
18423 &diff, mctx);
18424 if (result != ISC_R_SUCCESS) {
18425 dnssec_log(zone, ISC_LOG_ERROR,
18426 "zone_rekey:couldn't update CDS/CDNSKEY: %s",
18427 isc_result_totext(result));
18428 goto failure;
18429 }
18430
18431 /*
18432 * See if any pre-existing keys have newly become active;
18433 * also, see if any new key is for a new algorithm, as in that
18434 * event, we need to sign the zone fully. (If there's a new
18435 * key, but it's for an already-existing algorithm, then
18436 * the zone signing can be handled incrementally.)
18437 */
18438 for (key = ISC_LIST_HEAD(dnskeys);
18439 key != NULL;
18440 key = ISC_LIST_NEXT(key, link))
18441 {
18442 if (!key->first_sign) {
18443 continue;
18444 }
18445
18446 newactive = true;
18447
18448 if (!dns_rdataset_isassociated(&keysigs)) {
18449 newalg = true;
18450 break;
18451 }
18452
18453 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
18454 /*
18455 * This isn't a new algorithm; clear
18456 * first_sign so we won't sign the
18457 * whole zone with this key later
18458 */
18459 key->first_sign = false;
18460 } else {
18461 newalg = true;
18462 break;
18463 }
18464 }
18465
18466 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
18467 dnskey_sane(zone, db, ver, &diff))
18468 {
18469 CHECK(dns_diff_apply(&diff, db, ver));
18470 CHECK(clean_nsec3param(zone, db, ver, &diff));
18471 CHECK(add_signing_records(db, zone->privatetype,
18472 ver, &diff,
18473 (newalg || fullsign)));
18474 CHECK(update_soa_serial(db, ver, &diff, mctx,
18475 zone->updatemethod));
18476 CHECK(add_chains(zone, db, ver, &diff));
18477 CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
18478 CHECK(zone_journal(zone, zonediff.diff, NULL,
18479 "zone_rekey"));
18480 commit = true;
18481 }
18482 }
18483
18484 dns_db_closeversion(db, &ver, true);
18485
18486 if (commit) {
18487 dns_difftuple_t *tuple;
18488
18489 LOCK_ZONE(zone);
18490 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
18491
18492 zone_needdump(zone, DNS_DUMP_DELAY);
18493
18494 zone_settimer(zone, &timenow);
18495
18496 /* Remove any signatures from removed keys. */
18497 if (!ISC_LIST_EMPTY(rmkeys)) {
18498 for (key = ISC_LIST_HEAD(rmkeys);
18499 key != NULL;
18500 key = ISC_LIST_NEXT(key, link))
18501 {
18502 result = zone_signwithkey(zone,
18503 dst_key_alg(key->key),
18504 dst_key_id(key->key),
18505 true);
18506 if (result != ISC_R_SUCCESS) {
18507 dnssec_log(zone, ISC_LOG_ERROR,
18508 "zone_signwithkey failed: %s",
18509 dns_result_totext(result));
18510 }
18511 }
18512 }
18513
18514 if (fullsign) {
18515 /*
18516 * "rndc sign" was called, so we now sign the zone
18517 * with all active keys, whether they're new or not.
18518 */
18519 for (key = ISC_LIST_HEAD(dnskeys);
18520 key != NULL;
18521 key = ISC_LIST_NEXT(key, link))
18522 {
18523 if (!key->force_sign && !key->hint_sign) {
18524 continue;
18525 }
18526
18527 result = zone_signwithkey(zone,
18528 dst_key_alg(key->key),
18529 dst_key_id(key->key),
18530 false);
18531 if (result != ISC_R_SUCCESS) {
18532 dnssec_log(zone, ISC_LOG_ERROR,
18533 "zone_signwithkey failed: %s",
18534 dns_result_totext(result));
18535 }
18536 }
18537 } else if (newalg) {
18538 /*
18539 * We haven't been told to sign fully, but a new
18540 * algorithm was added to the DNSKEY. We sign
18541 * the full zone, but only with newly active
18542 * keys.
18543 */
18544 for (key = ISC_LIST_HEAD(dnskeys);
18545 key != NULL;
18546 key = ISC_LIST_NEXT(key, link))
18547 {
18548 if (!key->first_sign) {
18549 continue;
18550 }
18551
18552 result = zone_signwithkey(zone,
18553 dst_key_alg(key->key),
18554 dst_key_id(key->key),
18555 false);
18556 if (result != ISC_R_SUCCESS) {
18557 dnssec_log(zone, ISC_LOG_ERROR,
18558 "zone_signwithkey failed: %s",
18559 dns_result_totext(result));
18560 }
18561 }
18562 }
18563
18564 /*
18565 * Clear fullsign flag, if it was set, so we don't do
18566 * another full signing next time
18567 */
18568 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
18569
18570 /*
18571 * Cause the zone to add/delete NSEC3 chains for the
18572 * deferred NSEC3PARAM changes.
18573 */
18574 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
18575 tuple != NULL;
18576 tuple = ISC_LIST_NEXT(tuple, link))
18577 {
18578 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
18579 dns_rdata_t rdata = DNS_RDATA_INIT;
18580 dns_rdata_nsec3param_t nsec3param;
18581
18582 if (tuple->rdata.type != zone->privatetype ||
18583 tuple->op != DNS_DIFFOP_ADD)
18584 {
18585 continue;
18586 }
18587
18588 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
18589 buf, sizeof(buf)))
18590 {
18591 continue;
18592 }
18593
18594 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
18595 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18596 if (nsec3param.flags == 0) {
18597 continue;
18598 }
18599
18600 result = zone_addnsec3chain(zone, &nsec3param);
18601 if (result != ISC_R_SUCCESS) {
18602 dnssec_log(zone, ISC_LOG_ERROR,
18603 "zone_addnsec3chain failed: %s",
18604 dns_result_totext(result));
18605 }
18606 }
18607
18608 /*
18609 * Activate any NSEC3 chain updates that may have
18610 * been scheduled before this rekey.
18611 */
18612 if (fullsign || newalg) {
18613 resume_addnsec3chain(zone);
18614 }
18615
18616 /*
18617 * Schedule the next resigning event
18618 */
18619 set_resigntime(zone);
18620 UNLOCK_ZONE(zone);
18621 }
18622
18623 isc_time_settoepoch(&zone->refreshkeytime);
18624
18625 /*
18626 * If we're doing key maintenance, set the key refresh timer to
18627 * the next scheduled key event or to 'dnssec-loadkeys-interval'
18628 * seconds in the future, whichever is sooner.
18629 */
18630 if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
18631 isc_time_t timethen;
18632 isc_stdtime_t then;
18633
18634 LOCK_ZONE(zone);
18635 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
18636 &timethen);
18637 zone->refreshkeytime = timethen;
18638 UNLOCK_ZONE(zone);
18639
18640 for (key = ISC_LIST_HEAD(dnskeys);
18641 key != NULL;
18642 key = ISC_LIST_NEXT(key, link))
18643 {
18644 then = now;
18645 result = next_keyevent(key->key, &then);
18646 if (result != ISC_R_SUCCESS) {
18647 continue;
18648 }
18649
18650 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
18651 LOCK_ZONE(zone);
18652 if (isc_time_compare(&timethen,
18653 &zone->refreshkeytime) < 0)
18654 {
18655 zone->refreshkeytime = timethen;
18656 }
18657 UNLOCK_ZONE(zone);
18658 }
18659
18660 zone_settimer(zone, &timenow);
18661
18662 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
18663 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
18664 }
18665
18666 result = ISC_R_SUCCESS;
18667
18668 failure:
18669 if (result != ISC_R_SUCCESS) {
18670 /*
18671 * Something went wrong; try again in ten minutes or
18672 * after a key refresh interval, whichever is shorter.
18673 */
18674 isc_interval_set(&ival,
18675 ISC_MIN(zone->refreshkeyinterval, 600), 0);
18676 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
18677 }
18678
18679 dns_diff_clear(&diff);
18680 dns_diff_clear(&_sig_diff);
18681
18682 clear_keylist(&dnskeys, mctx);
18683 clear_keylist(&keys, mctx);
18684 clear_keylist(&rmkeys, mctx);
18685
18686 if (ver != NULL) {
18687 dns_db_closeversion(db, &ver, false);
18688 }
18689 if (dns_rdataset_isassociated(&cdsset)) {
18690 dns_rdataset_disassociate(&cdsset);
18691 }
18692 if (dns_rdataset_isassociated(&keyset)) {
18693 dns_rdataset_disassociate(&keyset);
18694 }
18695 if (dns_rdataset_isassociated(&keysigs)) {
18696 dns_rdataset_disassociate(&keysigs);
18697 }
18698 if (dns_rdataset_isassociated(&soasigs)) {
18699 dns_rdataset_disassociate(&soasigs);
18700 }
18701 if (dns_rdataset_isassociated(&cdnskeyset)) {
18702 dns_rdataset_disassociate(&cdnskeyset);
18703 }
18704 if (node != NULL) {
18705 dns_db_detachnode(db, &node);
18706 }
18707 if (db != NULL) {
18708 dns_db_detach(&db);
18709 }
18710
18711 INSIST(ver == NULL);
18712}
18713
18714void
18715dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
18716 isc_time_t now;
18717
18718 if (zone->type == dns_zone_master && zone->task != NULL) {
18719 LOCK_ZONE(zone);
18720
18721 if (fullsign)
18722 zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
18723
18724 TIME_NOW(&now);
18725 zone->refreshkeytime = now;
18726 zone_settimer(zone, &now);
18727
18728 UNLOCK_ZONE(zone);
18729 }
18730}
18731
18732isc_result_t
18733dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
18734 unsigned int *errors)
18735{
18736 isc_result_t result;
18737 dns_dbnode_t *node = NULL;
18738
18739 REQUIRE(DNS_ZONE_VALID(zone));
18740 REQUIRE(errors != NULL);
18741
18742 result = dns_db_getoriginnode(db, &node);
18743 if (result != ISC_R_SUCCESS)
18744 return (result);
18745 result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
18746 false);
18747 dns_db_detachnode(db, &node);
18748 return (result);
18749}
18750
18751isc_result_t
18752dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
18753 isc_result_t result;
18754 dns_dbnode_t *node = NULL;
18755 dns_rdataset_t dnskey, cds, cdnskey;
18756 unsigned char buffer[DNS_DS_BUFFERSIZE];
18757 unsigned char algorithms[256];
18758 unsigned int i;
18759
18760 REQUIRE(DNS_ZONE_VALID(zone));
18761
18762 result = dns_db_getoriginnode(db, &node);
18763 if (result != ISC_R_SUCCESS)
18764 return (result);
18765
18766 dns_rdataset_init(&cds);
18767 dns_rdataset_init(&dnskey);
18768 dns_rdataset_init(&cdnskey);
18769
18770 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
18771 dns_rdatatype_none, 0, &cds, NULL);
18772 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
18773 goto failure;
18774
18775 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
18776 dns_rdatatype_none, 0, &cdnskey, NULL);
18777 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
18778 goto failure;
18779
18780 if (!dns_rdataset_isassociated(&cds) &&
18781 !dns_rdataset_isassociated(&cdnskey)) {
18782 result = ISC_R_SUCCESS;
18783 goto failure;
18784 }
18785
18786 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
18787 dns_rdatatype_none, 0, &dnskey, NULL);
18788 if (result == ISC_R_NOTFOUND) {
18789 if (dns_rdataset_isassociated(&cds))
18790 result = DNS_R_BADCDS;
18791 else
18792 result = DNS_R_BADCDNSKEY;
18793 goto failure;
18794 }
18795 if (result != ISC_R_SUCCESS)
18796 goto failure;
18797
18798 /*
18799 * For each DNSSEC algorithm in the CDS RRset there must be
18800 * a matching DNSKEY record.
18801 */
18802 if (dns_rdataset_isassociated(&cds)) {
18803 memset(algorithms, 0, sizeof(algorithms));
18804 for (result = dns_rdataset_first(&cds);
18805 result == ISC_R_SUCCESS;
18806 result = dns_rdataset_next(&cds)) {
18807 dns_rdata_t crdata = DNS_RDATA_INIT;
18808 dns_rdata_cds_t structcds;
18809
18810 dns_rdataset_current(&cds, &crdata);
18811 CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
18812 if (algorithms[structcds.algorithm] == 0)
18813 algorithms[structcds.algorithm] = 1;
18814 for (result = dns_rdataset_first(&dnskey);
18815 result == ISC_R_SUCCESS;
18816 result = dns_rdataset_next(&dnskey)) {
18817 dns_rdata_t rdata = DNS_RDATA_INIT;
18818 dns_rdata_t dsrdata = DNS_RDATA_INIT;
18819
18820 dns_rdataset_current(&dnskey, &rdata);
18821 CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
18822 structcds.digest_type,
18823 buffer, &dsrdata));
18824 if (crdata.length == dsrdata.length &&
18825 memcmp(crdata.data, dsrdata.data,
18826 dsrdata.length) == 0) {
18827 algorithms[structcds.algorithm] = 2;
18828 }
18829 }
18830 if (result != ISC_R_NOMORE)
18831 goto failure;
18832 }
18833 for (i = 0; i < sizeof(algorithms); i++) {
18834 if (algorithms[i] == 1) {
18835 result = DNS_R_BADCDNSKEY;
18836 goto failure;
18837 }
18838 }
18839 }
18840
18841 /*
18842 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
18843 * a matching DNSKEY record.
18844 */
18845 if (dns_rdataset_isassociated(&cdnskey)) {
18846 memset(algorithms, 0, sizeof(algorithms));
18847 for (result = dns_rdataset_first(&cdnskey);
18848 result == ISC_R_SUCCESS;
18849 result = dns_rdataset_next(&cdnskey)) {
18850 dns_rdata_t crdata = DNS_RDATA_INIT;
18851 dns_rdata_cdnskey_t structcdnskey;
18852
18853 dns_rdataset_current(&cdnskey, &crdata);
18854 CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
18855 NULL));
18856 if (algorithms[structcdnskey.algorithm] == 0)
18857 algorithms[structcdnskey.algorithm] = 1;
18858 for (result = dns_rdataset_first(&dnskey);
18859 result == ISC_R_SUCCESS;
18860 result = dns_rdataset_next(&dnskey)) {
18861 dns_rdata_t rdata = DNS_RDATA_INIT;
18862
18863 dns_rdataset_current(&dnskey, &rdata);
18864 if (crdata.length == rdata.length &&
18865 memcmp(crdata.data, rdata.data,
18866 rdata.length) == 0) {
18867 algorithms[structcdnskey.algorithm] = 2;
18868 }
18869 }
18870 if (result != ISC_R_NOMORE)
18871 goto failure;
18872 }
18873 for (i = 0; i < sizeof(algorithms); i++) {
18874 if (algorithms[i] == 1) {
18875 result = DNS_R_BADCDS;
18876 goto failure;
18877 }
18878 }
18879 }
18880 result = ISC_R_SUCCESS;
18881
18882 failure:
18883 if (dns_rdataset_isassociated(&cds))
18884 dns_rdataset_disassociate(&cds);
18885 if (dns_rdataset_isassociated(&dnskey))
18886 dns_rdataset_disassociate(&dnskey);
18887 if (dns_rdataset_isassociated(&cdnskey))
18888 dns_rdataset_disassociate(&cdnskey);
18889 dns_db_detachnode(db, &node);
18890 return (result);
18891}
18892
18893void
18894dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
18895 REQUIRE(DNS_ZONE_VALID(zone));
18896
18897 LOCK_ZONE(zone);
18898 zone->automatic = automatic;
18899 UNLOCK_ZONE(zone);
18900}
18901
18902bool
18903dns_zone_getautomatic(dns_zone_t *zone) {
18904 REQUIRE(DNS_ZONE_VALID(zone));
18905 return (zone->automatic);
18906}
18907
18908void
18909dns_zone_setadded(dns_zone_t *zone, bool added) {
18910 REQUIRE(DNS_ZONE_VALID(zone));
18911
18912 LOCK_ZONE(zone);
18913 zone->added = added;
18914 UNLOCK_ZONE(zone);
18915}
18916
18917bool
18918dns_zone_getadded(dns_zone_t *zone) {
18919 REQUIRE(DNS_ZONE_VALID(zone));
18920 return (zone->added);
18921}
18922
18923isc_result_t
18924dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
18925{
18926 isc_time_t loadtime;
18927 isc_result_t result;
18928 dns_zone_t *secure = NULL;
18929
18930 TIME_NOW(&loadtime);
18931
18932 /*
18933 * Lock hierarchy: zmgr, zone, raw.
18934 */
18935 again:
18936 LOCK_ZONE(zone);
18937 INSIST(zone != zone->raw);
18938 if (inline_secure(zone))
18939 LOCK_ZONE(zone->raw);
18940 else if (inline_raw(zone)) {
18941 secure = zone->secure;
18942 TRYLOCK_ZONE(result, secure);
18943 if (result != ISC_R_SUCCESS) {
18944 UNLOCK_ZONE(zone);
18945 secure = NULL;
18946 isc_thread_yield();
18947 goto again;
18948 }
18949 }
18950 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
18951 if (inline_secure(zone))
18952 UNLOCK_ZONE(zone->raw);
18953 else if (secure != NULL)
18954 UNLOCK_ZONE(secure);
18955 UNLOCK_ZONE(zone);
18956 return result;
18957}
18958
18959isc_result_t
18960dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
18961 REQUIRE(DNS_ZONE_VALID(zone));
18962 if (interval == 0)
18963 return (ISC_R_RANGE);
18964 /* Maximum value: 24 hours (3600 minutes) */
18965 if (interval > (24 * 60))
18966 interval = (24 * 60);
18967 /* Multiply by 60 for seconds */
18968 zone->refreshkeyinterval = interval * 60;
18969 return (ISC_R_SUCCESS);
18970}
18971
18972void
18973dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
18974 REQUIRE(DNS_ZONE_VALID(zone));
18975 zone->requestixfr = flag;
18976}
18977
18978bool
18979dns_zone_getrequestixfr(dns_zone_t *zone) {
18980 REQUIRE(DNS_ZONE_VALID(zone));
18981 return (zone->requestixfr);
18982}
18983
18984void
18985dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
18986 REQUIRE(DNS_ZONE_VALID(zone));
18987 zone->requestexpire = flag;
18988}
18989
18990bool
18991dns_zone_getrequestexpire(dns_zone_t *zone) {
18992 REQUIRE(DNS_ZONE_VALID(zone));
18993 return (zone->requestexpire);
18994}
18995
18996void
18997dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
18998 REQUIRE(DNS_ZONE_VALID(zone));
18999 zone->updatemethod = method;
19000}
19001
19002dns_updatemethod_t
19003dns_zone_getserialupdatemethod(dns_zone_t *zone) {
19004 REQUIRE(DNS_ZONE_VALID(zone));
19005 return(zone->updatemethod);
19006}
19007
19008/*
19009 * Lock hierarchy: zmgr, zone, raw.
19010 */
19011isc_result_t
19012dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
19013 isc_result_t result;
19014 dns_zonemgr_t *zmgr;
19015
19016 REQUIRE(DNS_ZONE_VALID(zone));
19017 REQUIRE(zone->zmgr != NULL);
19018 REQUIRE(zone->task != NULL);
19019 REQUIRE(zone->loadtask != NULL);
19020 REQUIRE(zone->raw == NULL);
19021
19022 REQUIRE(DNS_ZONE_VALID(raw));
19023 REQUIRE(raw->zmgr == NULL);
19024 REQUIRE(raw->task == NULL);
19025 REQUIRE(raw->loadtask == NULL);
19026 REQUIRE(raw->secure == NULL);
19027
19028 REQUIRE(zone != raw);
19029
19030 /*
19031 * Lock hierarchy: zmgr, zone, raw.
19032 */
19033 zmgr = zone->zmgr;
19034 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19035 LOCK_ZONE(zone);
19036 LOCK_ZONE(raw);
19037
19038 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
19039 NULL, NULL, zone->task, zone_timer, raw,
19040 &raw->timer);
19041 if (result != ISC_R_SUCCESS)
19042 goto unlock;
19043
19044 /*
19045 * The timer "holds" a iref.
19046 */
19047 raw->irefs++;
19048 INSIST(raw->irefs != 0);
19049
19050
19051 /* dns_zone_attach(raw, &zone->raw); */
19052 isc_refcount_increment(&raw->erefs);
19053 zone->raw = raw;
19054
19055 /* dns_zone_iattach(zone, &raw->secure); */
19056 zone_iattach(zone, &raw->secure);
19057
19058 isc_task_attach(zone->task, &raw->task);
19059 isc_task_attach(zone->loadtask, &raw->loadtask);
19060
19061 ISC_LIST_APPEND(zmgr->zones, raw, link);
19062 raw->zmgr = zmgr;
19063 zmgr->refs++;
19064
19065 unlock:
19066 UNLOCK_ZONE(raw);
19067 UNLOCK_ZONE(zone);
19068 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19069 return (result);
19070}
19071
19072void
19073dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
19074 REQUIRE(DNS_ZONE_VALID(zone));
19075 REQUIRE(raw != NULL && *raw == NULL);
19076
19077 LOCK(&zone->lock);
19078 INSIST(zone != zone->raw);
19079 if (zone->raw != NULL)
19080 dns_zone_attach(zone->raw, raw);
19081 UNLOCK(&zone->lock);
19082}
19083
19084struct keydone {
19085 isc_event_t event;
19086 bool all;
19087 unsigned char data[5];
19088};
19089
19090#define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
19091
19092static void
19093keydone(isc_task_t *task, isc_event_t *event) {
19094 const char *me = "keydone";
19095 bool commit = false;
19096 isc_result_t result;
19097 dns_rdata_t rdata = DNS_RDATA_INIT;
19098 dns_dbversion_t *oldver = NULL, *newver = NULL;
19099 dns_zone_t *zone;
19100 dns_db_t *db = NULL;
19101 dns_dbnode_t *node = NULL;
19102 dns_rdataset_t rdataset;
19103 dns_diff_t diff;
19104 struct keydone *kd = (struct keydone *)event;
19105 dns_update_log_t log = { update_log_cb, NULL };
19106 bool clear_pending = false;
19107
19108 UNUSED(task);
19109
19110 zone = event->ev_arg;
19111 INSIST(DNS_ZONE_VALID(zone));
19112
19113 ENTER;
19114
19115 dns_rdataset_init(&rdataset);
19116 dns_diff_init(zone->mctx, &diff);
19117
19118 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19119 if (zone->db != NULL) {
19120 dns_db_attach(zone->db, &db);
19121 }
19122 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19123 if (db == NULL) {
19124 goto failure;
19125 }
19126
19127 dns_db_currentversion(db, &oldver);
19128 result = dns_db_newversion(db, &newver);
19129 if (result != ISC_R_SUCCESS) {
19130 dnssec_log(zone, ISC_LOG_ERROR,
19131 "keydone:dns_db_newversion -> %s",
19132 dns_result_totext(result));
19133 goto failure;
19134 }
19135
19136 result = dns_db_getoriginnode(db, &node);
19137 if (result != ISC_R_SUCCESS) {
19138 goto failure;
19139 }
19140
19141 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
19142 dns_rdatatype_none, 0, &rdataset, NULL);
19143 if (result == ISC_R_NOTFOUND) {
19144 INSIST(!dns_rdataset_isassociated(&rdataset));
19145 goto failure;
19146 }
19147 if (result != ISC_R_SUCCESS) {
19148 INSIST(!dns_rdataset_isassociated(&rdataset));
19149 goto failure;
19150 }
19151
19152 for (result = dns_rdataset_first(&rdataset);
19153 result == ISC_R_SUCCESS;
19154 result = dns_rdataset_next(&rdataset))
19155 {
19156 bool found = false;
19157
19158 dns_rdataset_current(&rdataset, &rdata);
19159
19160 if (kd->all) {
19161 if (rdata.length == 5 && rdata.data[0] != 0 &&
19162 rdata.data[3] == 0 && rdata.data[4] == 1)
19163 {
19164 found = true;
19165 } else if (rdata.data[0] == 0 &&
19166 (rdata.data[2] & PENDINGFLAGS) != 0)
19167 {
19168 found = true;
19169 clear_pending = true;
19170 }
19171 } else if (rdata.length == 5 &&
19172 memcmp(rdata.data, kd->data, 5) == 0)
19173 {
19174 found = true;
19175 }
19176
19177 if (found) {
19178 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
19179 &zone->origin, rdataset.ttl,
19180 &rdata));
19181 }
19182 dns_rdata_reset(&rdata);
19183 }
19184
19185 if (!ISC_LIST_EMPTY(diff.tuples)) {
19186 /* Write changes to journal file. */
19187 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
19188 zone->updatemethod));
19189
19190 result = dns_update_signatures(&log, zone, db,
19191 oldver, newver, &diff,
19192 zone->sigvalidityinterval);
19193 if (!clear_pending) {
19194 CHECK(result);
19195 }
19196
19197 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
19198 commit = true;
19199
19200 LOCK_ZONE(zone);
19201 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
19202 zone_needdump(zone, 30);
19203 UNLOCK_ZONE(zone);
19204 }
19205
19206 failure:
19207 if (dns_rdataset_isassociated(&rdataset)) {
19208 dns_rdataset_disassociate(&rdataset);
19209 }
19210 if (db != NULL) {
19211 if (node != NULL) {
19212 dns_db_detachnode(db, &node);
19213 }
19214 if (oldver != NULL) {
19215 dns_db_closeversion(db, &oldver, false);
19216 }
19217 if (newver != NULL) {
19218 dns_db_closeversion(db, &newver, commit);
19219 }
19220 dns_db_detach(&db);
19221 }
19222 dns_diff_clear(&diff);
19223 isc_event_free(&event);
19224 dns_zone_idetach(&zone);
19225
19226 INSIST(oldver == NULL);
19227 INSIST(newver == NULL);
19228}
19229
19230isc_result_t
19231dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
19232 isc_result_t result = ISC_R_SUCCESS;
19233 isc_event_t *e;
19234 isc_buffer_t b;
19235 dns_zone_t *dummy = NULL;
19236 struct keydone *kd;
19237
19238 REQUIRE(DNS_ZONE_VALID(zone));
19239
19240 LOCK_ZONE(zone);
19241
19242 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
19243 zone, sizeof(struct keydone));
19244 if (e == NULL) {
19245 result = ISC_R_NOMEMORY;
19246 goto failure;
19247 }
19248
19249 kd = (struct keydone *) e;
19250 if (strcasecmp(keystr, "all") == 0) {
19251 kd->all = true;
19252 } else {
19253 isc_textregion_t r;
19254 const char *algstr;
19255 dns_keytag_t keyid;
19256 dns_secalg_t alg;
19257 size_t n;
19258
19259 kd->all = false;
19260
19261 n = sscanf(keystr, "%hu/", &keyid);
19262 if (n == 0U) {
19263 CHECK(ISC_R_FAILURE);
19264 }
19265
19266 algstr = strchr(keystr, '/');
19267 if (algstr != NULL) {
19268 algstr++;
19269 } else {
19270 CHECK(ISC_R_FAILURE);
19271 }
19272
19273 n = sscanf(algstr, "%hhu", &alg);
19274 if (n == 0U) {
19275 DE_CONST(algstr, r.base);
19276 r.length = strlen(algstr);
19277 CHECK(dns_secalg_fromtext(&alg, &r));
19278 }
19279
19280 /* construct a private-type rdata */
19281 isc_buffer_init(&b, kd->data, sizeof(kd->data));
19282 isc_buffer_putuint8(&b, alg);
19283 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
19284 isc_buffer_putuint8(&b, (keyid & 0xff));
19285 isc_buffer_putuint8(&b, 0);
19286 isc_buffer_putuint8(&b, 1);
19287 }
19288
19289 zone_iattach(zone, &dummy);
19290 isc_task_send(zone->task, &e);
19291
19292 failure:
19293 if (e != NULL) {
19294 isc_event_free(&e);
19295 }
19296 UNLOCK_ZONE(zone);
19297 return (result);
19298}
19299
19300/*
19301 * Called from the zone task's queue after the relevant event is posted by
19302 * dns_zone_setnsec3param().
19303 *
19304 * Check whether NSEC3 chain addition or removal specified by the private-type
19305 * record passed with the event was already queued (or even fully performed).
19306 * If not, modify the relevant private-type records at the zone apex and call
19307 * resume_addnsec3chain().
19308 */
19309static void
19310setnsec3param(isc_task_t *task, isc_event_t *event) {
19311 const char *me = "setnsec3param";
19312 bool commit = false;
19313 isc_result_t result;
19314 dns_dbversion_t *oldver = NULL, *newver = NULL;
19315 dns_zone_t *zone;
19316 dns_db_t *db = NULL;
19317 dns_dbnode_t *node = NULL;
19318 dns_rdataset_t prdataset, nrdataset;
19319 dns_diff_t diff;
19320 struct np3event *npe = (struct np3event *)event;
19321 nsec3param_t *np;
19322 dns_update_log_t log = { update_log_cb, NULL };
19323 dns_rdata_t rdata;
19324 bool nseconly;
19325 bool exists = false;
19326
19327 UNUSED(task);
19328
19329 zone = event->ev_arg;
19330 INSIST(DNS_ZONE_VALID(zone));
19331
19332 ENTER;
19333
19334 np = &npe->params;
19335
19336 dns_rdataset_init(&prdataset);
19337 dns_rdataset_init(&nrdataset);
19338 dns_diff_init(zone->mctx, &diff);
19339
19340 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19341 if (zone->db != NULL) {
19342 dns_db_attach(zone->db, &db);
19343 }
19344 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19345 if (db == NULL) {
19346 goto failure;
19347 }
19348
19349 dns_db_currentversion(db, &oldver);
19350 result = dns_db_newversion(db, &newver);
19351 if (result != ISC_R_SUCCESS) {
19352 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19353 dnssec_log(zone, ISC_LOG_ERROR,
19354 "setnsec3param:dns_db_newversion -> %s",
19355 dns_result_totext(result));
19356 goto failure;
19357 }
19358
19359 CHECK(dns_db_getoriginnode(db, &node));
19360
19361 /*
19362 * Does a private-type record already exist for this chain?
19363 */
19364 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
19365 dns_rdatatype_none, 0, &prdataset, NULL);
19366 if (result == ISC_R_SUCCESS) {
19367 for (result = dns_rdataset_first(&prdataset);
19368 result == ISC_R_SUCCESS;
19369 result = dns_rdataset_next(&prdataset))
19370 {
19371 dns_rdata_init(&rdata);
19372 dns_rdataset_current(&prdataset, &rdata);
19373
19374 if (np->length == rdata.length &&
19375 memcmp(rdata.data, np->data, np->length) == 0)
19376 {
19377 exists = true;
19378 break;
19379 }
19380 }
19381 } else if (result != ISC_R_NOTFOUND) {
19382 INSIST(!dns_rdataset_isassociated(&prdataset));
19383 goto failure;
19384 }
19385
19386 /*
19387 * Does the chain already exist?
19388 */
19389 result = dns_db_findrdataset(db, node, newver,
19390 dns_rdatatype_nsec3param,
19391 dns_rdatatype_none, 0, &nrdataset, NULL);
19392 if (result == ISC_R_SUCCESS) {
19393 for (result = dns_rdataset_first(&nrdataset);
19394 result == ISC_R_SUCCESS;
19395 result = dns_rdataset_next(&nrdataset))
19396 {
19397 dns_rdata_init(&rdata);
19398 dns_rdataset_current(&nrdataset, &rdata);
19399
19400 if (np->length == (rdata.length + 1) &&
19401 memcmp(rdata.data, np->data + 1,
19402 np->length - 1) == 0)
19403 {
19404 exists = true;
19405 break;
19406 }
19407 }
19408 } else if (result != ISC_R_NOTFOUND) {
19409 INSIST(!dns_rdataset_isassociated(&nrdataset));
19410 goto failure;
19411 }
19412
19413
19414 /*
19415 * We need to remove any existing NSEC3 chains if the supplied NSEC3
19416 * parameters are supposed to replace the current ones or if we are
19417 * switching to NSEC.
19418 */
19419 if (!exists && np->replace && (np->length != 0 || np->nsec)) {
19420 CHECK(dns_nsec3param_deletechains(db, newver, zone,
19421 !np->nsec, &diff));
19422 }
19423
19424 if (!exists && np->length != 0) {
19425 /*
19426 * We're creating an NSEC3 chain. Add the private-type record
19427 * passed in the event handler's argument to the zone apex.
19428 *
19429 * If the zone is not currently capable of supporting an NSEC3
19430 * chain (due to the DNSKEY RRset at the zone apex not existing
19431 * or containing at least one key using an NSEC-only
19432 * algorithm), add the INITIAL flag, so these parameters can be
19433 * used later when NSEC3 becomes available.
19434 */
19435 dns_rdata_init(&rdata);
19436
19437 np->data[2] |= DNS_NSEC3FLAG_CREATE;
19438 result = dns_nsec_nseconly(db, newver, &nseconly);
19439 if (result == ISC_R_NOTFOUND || nseconly) {
19440 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
19441 }
19442
19443 rdata.length = np->length;
19444 rdata.data = np->data;
19445 rdata.type = zone->privatetype;
19446 rdata.rdclass = zone->rdclass;
19447 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
19448 &zone->origin, 0, &rdata));
19449 }
19450
19451 /*
19452 * If we changed anything in the zone, write changes to journal file
19453 * and set commit to true so that resume_addnsec3chain() will be
19454 * called below in order to kick off adding/removing relevant NSEC3
19455 * records.
19456 */
19457 if (!ISC_LIST_EMPTY(diff.tuples)) {
19458 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
19459 zone->updatemethod));
19460 result = dns_update_signatures(&log, zone, db,
19461 oldver, newver, &diff,
19462 zone->sigvalidityinterval);
19463 if (result != ISC_R_NOTFOUND) {
19464 CHECK(result);
19465 }
19466 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
19467 commit = true;
19468
19469 LOCK_ZONE(zone);
19470 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
19471 zone_needdump(zone, 30);
19472 UNLOCK_ZONE(zone);
19473 }
19474
19475 failure:
19476 if (dns_rdataset_isassociated(&prdataset)) {
19477 dns_rdataset_disassociate(&prdataset);
19478 }
19479 if (dns_rdataset_isassociated(&nrdataset)) {
19480 dns_rdataset_disassociate(&nrdataset);
19481 }
19482 if (node != NULL) {
19483 dns_db_detachnode(db, &node);
19484 }
19485 if (oldver != NULL) {
19486 dns_db_closeversion(db, &oldver, false);
19487 }
19488 if (newver != NULL) {
19489 dns_db_closeversion(db, &newver, commit);
19490 }
19491 if (db != NULL) {
19492 dns_db_detach(&db);
19493 }
19494 if (commit) {
19495 LOCK_ZONE(zone);
19496 resume_addnsec3chain(zone);
19497 UNLOCK_ZONE(zone);
19498 }
19499 dns_diff_clear(&diff);
19500 isc_event_free(&event);
19501 dns_zone_idetach(&zone);
19502
19503 INSIST(oldver == NULL);
19504 INSIST(newver == NULL);
19505}
19506
19507/*
19508 * Called when an "rndc signing -nsec3param ..." command is received.
19509 *
19510 * Allocate and prepare an nsec3param_t structure which holds information about
19511 * the NSEC3 changes requested for the zone:
19512 *
19513 * - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
19514 * field of the structure to true and the "replace" field to the value
19515 * of the "replace" argument, leaving other fields initialized to zeros, to
19516 * signal that the zone should be signed using NSEC instead of NSEC3,
19517 *
19518 * - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
19519 * the zone apex, convert it to a private-type record and store the latter
19520 * in the "data" field of the nsec3param_t structure.
19521 *
19522 * Once the nsec3param_t structure is prepared, post an event to the zone's
19523 * task which will cause setnsec3param() to be called with the prepared
19524 * structure passed as an argument.
19525 */
19526isc_result_t
19527dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
19528 uint16_t iter, uint8_t saltlen,
19529 unsigned char *salt, bool replace)
19530{
19531 isc_result_t result = ISC_R_SUCCESS;
19532 dns_rdata_nsec3param_t param;
19533 dns_rdata_t nrdata = DNS_RDATA_INIT;
19534 dns_rdata_t prdata = DNS_RDATA_INIT;
19535 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
19536 struct np3event *npe;
19537 nsec3param_t *np;
19538 dns_zone_t *dummy = NULL;
19539 isc_buffer_t b;
19540 isc_event_t *e;
19541
19542 REQUIRE(DNS_ZONE_VALID(zone));
19543 REQUIRE(salt != NULL);
19544
19545 LOCK_ZONE(zone);
19546
19547 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
19548 setnsec3param, zone, sizeof(struct np3event));
19549 if (e == NULL) {
19550 result = ISC_R_NOMEMORY;
19551 goto failure;
19552 }
19553
19554 npe = (struct np3event *) e;
19555 np = &npe->params;
19556
19557 np->replace = replace;
19558 if (hash == 0) {
19559 np->length = 0;
19560 np->nsec = true;
19561 } else {
19562 param.common.rdclass = zone->rdclass;
19563 param.common.rdtype = dns_rdatatype_nsec3param;
19564 ISC_LINK_INIT(&param.common, link);
19565 param.mctx = NULL;
19566 param.hash = hash;
19567 param.flags = flags;
19568 param.iterations = iter;
19569 param.salt_length = saltlen;
19570 param.salt = salt;
19571 isc_buffer_init(&b, nbuf, sizeof(nbuf));
19572 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
19573 dns_rdatatype_nsec3param,
19574 &param, &b));
19575 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
19576 np->data, sizeof(np->data));
19577 np->length = prdata.length;
19578 np->nsec = false;
19579 }
19580
19581 /*
19582 * setnsec3param() will silently return early if the zone does not yet
19583 * have a database. Prevent that by queueing the event up if zone->db
19584 * is NULL. All events queued here are subsequently processed by
19585 * receive_secure_db() if it ever gets called or simply freed by
19586 * zone_free() otherwise.
19587 */
19588 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19589 if (zone->db != NULL) {
19590 zone_iattach(zone, &dummy);
19591 isc_task_send(zone->task, &e);
19592 } else {
19593 ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
19594 e = NULL;
19595 }
19596 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19597
19598 failure:
19599 if (e != NULL) {
19600 isc_event_free(&e);
19601 }
19602 UNLOCK_ZONE(zone);
19603 return (result);
19604}
19605
19606isc_result_t
19607dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
19608 REQUIRE(DNS_ZONE_VALID(zone));
19609 REQUIRE(loadtime != NULL);
19610
19611 LOCK_ZONE(zone);
19612 *loadtime = zone->loadtime;
19613 UNLOCK_ZONE(zone);
19614 return (ISC_R_SUCCESS);
19615}
19616
19617isc_result_t
19618dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
19619 REQUIRE(DNS_ZONE_VALID(zone));
19620 REQUIRE(expiretime != NULL);
19621
19622 LOCK_ZONE(zone);
19623 *expiretime = zone->expiretime;
19624 UNLOCK_ZONE(zone);
19625 return (ISC_R_SUCCESS);
19626}
19627
19628isc_result_t
19629dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
19630 REQUIRE(DNS_ZONE_VALID(zone));
19631 REQUIRE(refreshtime != NULL);
19632
19633 LOCK_ZONE(zone);
19634 *refreshtime = zone->refreshtime;
19635 UNLOCK_ZONE(zone);
19636 return (ISC_R_SUCCESS);
19637}
19638
19639isc_result_t
19640dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
19641 REQUIRE(DNS_ZONE_VALID(zone));
19642 REQUIRE(refreshkeytime != NULL);
19643
19644 LOCK_ZONE(zone);
19645 *refreshkeytime = zone->refreshkeytime;
19646 UNLOCK_ZONE(zone);
19647 return (ISC_R_SUCCESS);
19648}
19649
19650unsigned int
19651dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
19652 dns_include_t *include;
19653 char **array = NULL;
19654 unsigned int n = 0;
19655
19656 REQUIRE(DNS_ZONE_VALID(zone));
19657 REQUIRE(includesp != NULL && *includesp == NULL);
19658
19659 LOCK_ZONE(zone);
19660 if (zone->nincludes == 0)
19661 goto done;
19662
19663 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
19664 if (array == NULL)
19665 goto done;
19666 for (include = ISC_LIST_HEAD(zone->includes);
19667 include != NULL;
19668 include = ISC_LIST_NEXT(include, link)) {
19669 INSIST(n < zone->nincludes);
19670 array[n++] = isc_mem_strdup(zone->mctx, include->name);
19671 }
19672 INSIST(n == zone->nincludes);
19673 *includesp = array;
19674
19675 done:
19676 UNLOCK_ZONE(zone);
19677 return (n);
19678}
19679
19680void
19681dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
19682 REQUIRE(DNS_ZONE_VALID(zone));
19683
19684 zone->statlevel = level;
19685}
19686
19687dns_zonestat_level_t
19688dns_zone_getstatlevel(dns_zone_t *zone) {
19689 REQUIRE(DNS_ZONE_VALID(zone));
19690
19691 return (zone->statlevel);
19692}
19693
19694static void
19695setserial(isc_task_t *task, isc_event_t *event) {
19696 uint32_t oldserial, desired;
19697 const char *me = "setserial";
19698 bool commit = false;
19699 isc_result_t result;
19700 dns_dbversion_t *oldver = NULL, *newver = NULL;
19701 dns_zone_t *zone;
19702 dns_db_t *db = NULL;
19703 dns_diff_t diff;
19704 struct ssevent *sse = (struct ssevent *)event;
19705 dns_update_log_t log = { update_log_cb, NULL };
19706 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
19707
19708 UNUSED(task);
19709
19710 zone = event->ev_arg;
19711 INSIST(DNS_ZONE_VALID(zone));
19712
19713 ENTER;
19714
19715 if (zone->update_disabled)
19716 goto failure;
19717
19718 desired = sse->serial;
19719
19720 dns_diff_init(zone->mctx, &diff);
19721
19722 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19723 if (zone->db != NULL)
19724 dns_db_attach(zone->db, &db);
19725 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19726 if (db == NULL)
19727 goto failure;
19728
19729 dns_db_currentversion(db, &oldver);
19730 result = dns_db_newversion(db, &newver);
19731 if (result != ISC_R_SUCCESS) {
19732 dns_zone_log(zone, ISC_LOG_ERROR,
19733 "setserial:dns_db_newversion -> %s",
19734 dns_result_totext(result));
19735 goto failure;
19736 }
19737
19738 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
19739 DNS_DIFFOP_DEL, &oldtuple));
19740 CHECK(dns_difftuple_copy(oldtuple, &newtuple));
19741 newtuple->op = DNS_DIFFOP_ADD;
19742
19743 oldserial = dns_soa_getserial(&oldtuple->rdata);
19744 if (desired == 0U)
19745 desired = 1;
19746 if (!isc_serial_gt(desired, oldserial)) {
19747 if (desired != oldserial)
19748 dns_zone_log(zone, ISC_LOG_INFO,
19749 "setserial: desired serial (%u) "
19750 "out of range (%u-%u)", desired,
19751 oldserial + 1, (oldserial + 0x7fffffff));
19752 goto failure;
19753 }
19754
19755 dns_soa_setserial(desired, &newtuple->rdata);
19756 CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
19757 CHECK(do_one_tuple(&newtuple, db, newver, &diff));
19758 result = dns_update_signatures(&log, zone, db,
19759 oldver, newver, &diff,
19760 zone->sigvalidityinterval);
19761 if (result != ISC_R_NOTFOUND)
19762 CHECK(result);
19763
19764 /* Write changes to journal file. */
19765 CHECK(zone_journal(zone, &diff, NULL, "setserial"));
19766 commit = true;
19767
19768 LOCK_ZONE(zone);
19769 zone_needdump(zone, 30);
19770 UNLOCK_ZONE(zone);
19771
19772 failure:
19773 if (oldtuple != NULL)
19774 dns_difftuple_free(&oldtuple);
19775 if (newtuple != NULL)
19776 dns_difftuple_free(&newtuple);
19777 if (oldver != NULL)
19778 dns_db_closeversion(db, &oldver, false);
19779 if (newver != NULL)
19780 dns_db_closeversion(db, &newver, commit);
19781 if (db != NULL)
19782 dns_db_detach(&db);
19783 dns_diff_clear(&diff);
19784 isc_event_free(&event);
19785 dns_zone_idetach(&zone);
19786
19787 INSIST(oldver == NULL);
19788 INSIST(newver == NULL);
19789}
19790
19791isc_result_t
19792dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
19793 isc_result_t result = ISC_R_SUCCESS;
19794 dns_zone_t *dummy = NULL;
19795 isc_event_t *e = NULL;
19796 struct ssevent *sse;
19797
19798 REQUIRE(DNS_ZONE_VALID(zone));
19799
19800 LOCK_ZONE(zone);
19801
19802 if (!inline_secure(zone)) {
19803 if (!dns_zone_isdynamic(zone, true)) {
19804 result = DNS_R_NOTDYNAMIC;
19805 goto failure;
19806 }
19807 }
19808
19809 if (zone->update_disabled) {
19810 result = DNS_R_FROZEN;
19811 goto failure;
19812 }
19813
19814 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL,
19815 setserial, zone, sizeof(struct ssevent));
19816 if (e == NULL) {
19817 result = ISC_R_NOMEMORY;
19818 goto failure;
19819 }
19820
19821 sse = (struct ssevent *)e;
19822 sse->serial = serial;
19823
19824 zone_iattach(zone, &dummy);
19825 isc_task_send(zone->task, &e);
19826
19827 failure:
19828 if (e != NULL)
19829 isc_event_free(&e);
19830 UNLOCK_ZONE(zone);
19831 return (result);
19832}
19833
19834isc_stats_t *
19835dns_zone_getgluecachestats(dns_zone_t *zone) {
19836 REQUIRE(DNS_ZONE_VALID(zone));
19837
19838 return (zone->gluecachestats);
19839}
19840
19841bool
19842dns_zone_isloaded(const dns_zone_t *zone) {
19843 REQUIRE(DNS_ZONE_VALID(zone));
19844
19845 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
19846}
19847
19848isc_result_t
19849dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
19850 dns_dbversion_t *version = NULL;
19851 dns_keytable_t *secroots = NULL;
19852 isc_result_t result;
19853 dns_name_t *origin;
19854
19855 const char me[] = "dns_zone_verifydb";
19856 ENTER;
19857
19858 REQUIRE(DNS_ZONE_VALID(zone));
19859 REQUIRE(db != NULL);
19860
19861 if (dns_zone_gettype(zone) != dns_zone_mirror) {
19862 return (ISC_R_SUCCESS);
19863 }
19864
19865 if (ver == NULL) {
19866 dns_db_currentversion(db, &version);
19867 } else {
19868 version = ver;
19869 }
19870
19871 if (zone->view != NULL) {
19872 result = dns_view_getsecroots(zone->view, &secroots);
19873 if (result != ISC_R_SUCCESS) {
19874 goto done;
19875 }
19876 }
19877
19878 origin = dns_db_origin(db);
19879 result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
19880 zone->mctx, true, false);
19881
19882 done:
19883 if (secroots != NULL) {
19884 dns_keytable_detach(&secroots);
19885 }
19886
19887 if (ver == NULL) {
19888 dns_db_closeversion(db, &version, false);
19889 }
19890
19891 if (result != ISC_R_SUCCESS) {
19892 dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
19893 isc_result_totext(result));
19894 result = DNS_R_VERIFYFAILURE;
19895 }
19896
19897 return (result);
19898}
19899